关于添加列时zoo系列中的r:If语句

If statement in zoo series when adding a column

我有以下动物园系列:

1
2
3
4
5
6
7
8
9
head(prices.zoo)

         JetFuel HeatingOil  Spread
Sep 1996   0.682     0.6794  0.0026
Oct 1996   0.703     0.7307 -0.0277
Nov 1996   0.696     0.7261 -0.0301
Dec 1996   0.693     0.7171 -0.0241
Jan 1997   0.680     0.7142 -0.0342
Feb 1997   0.619     0.6081  0.0109

我的目标是添加第 4 列操作,当 Spread>0 时为 1,当 Spread<0 时为 -1。我尝试了以下代码:

1
2
3
4
5
6
f <-function(x){
if(x>0) y=1
else y= -1
return(y)}

prices.zoo$Action <- sapply(prices.zoo$Spread,f)

弹出警告信息:"警告信息:
如果 (x > 0) y = 1000 否则 y = -100 :
条件的长度 > 1,并且只会使用第一个元素"
而结果显然是错误的:

1
2
3
4
5
6
7
         JetFuel HeatingOil  Spread Action
Sep 1996   0.682     0.6794  0.0026      1
Oct 1996   0.703     0.7307 -0.0277      1
Nov 1996   0.696     0.7261 -0.0301      1
Dec 1996   0.693     0.7171 -0.0241      1
Jan 1997   0.680     0.7142 -0.0342      1
Feb 1997   0.619     0.6081  0.0109      1

但是在我将动物园系列转换为数据框后,一切正常:

1
2
3
4
5
6
7
8
9
10
11
prices.zoo.df <- data.frame(prices.zoo)
prices.zoo.df$Action <- sapply(prices.zoo.df$Spread,f)
head(prices.zoo.df)

         JetFuel HeatingOil  Spread Action
Sep 1996   0.682     0.6794  0.0026      1
Oct 1996   0.703     0.7307 -0.0277     -1
Nov 1996   0.696     0.7261 -0.0301     -1
Dec 1996   0.693     0.7171 -0.0241     -1
Jan 1997   0.680     0.7142 -0.0342     -1
Feb 1997   0.619     0.6081  0.0109      1

谁能向我解释为什么会这样?有没有什么办法不用移动到数据框就可以在zoo系列上实现同样的效果?

可重现的例子

1
2
3
4
5
6
7
8
z <- zoo(cbind(c1 = c(1,2,3,-1,-2)),Sys.Date()+0:4)

f <-function(x){
if(x>0) y=1
else y= -1
return(y)}

z$c2 <- sapply(z$c1,f)

^这种带有 sapply 的方法产生以下输出(不是我要找的):

1
2
3
4
5
6
           c1 c2
2017-05-09  1  1
2017-05-10  2  1
2017-05-11  3  1
2017-05-12 -1  1
2017-05-13 -2  1

在上述动物园系列被转换为数据框后,与 sapply 相同的方法有效:

1
2
3
4
5
6
7
8
9
10
z <- data.frame(z)
z$c2 <- sapply(z$c1,f)
z

           c1 c2
2017-05-09  1  1
2017-05-10  2  1
2017-05-11  3  1
2017-05-12 -1 -1
2017-05-13 -2 -1


这些都行:

1
2
3
4
5
6
7
8
9
10
11
# 1
prices.zoo$Action <- sign(prices.zoo$Spread)

# 2
prices.zoo$Action <- (prices.zoo$Spread > 0) - (prices.zoo$Spread < 0)

# 3
prices.zoo$Action <- ifelse(prices.zoo$Spread > 0, 1, -1)

# 4
prices.zoo$Action <- sapply(coredata(prices.zoo$Spread), f)

通常我们不会使用 sapply,除非没有它就无法向量化问题。