我是R的新手,并且一直在努力解决以下问题,所以我希望有人能够帮助我。
样本数据代表股票价格回报(每行是一个月周期)。实际数据集要大得多,其结构类似于以下输入:
输入:
stock1 <- c(0.01, -0.02, 0.01, 0.05, 0.04, -0.02)
stock2 <- c(0, 0, 0.02, 0.04, -0.03, 0.02)
stock3 <- c(0, 0, 0.02, 0, -0.01, 0.03)
stock4 <- c(0, -0.02, 0.01, 0, 0, -0.02)
df <- cbind(stock1,stock2,stock3,stock4)
stock1 stock2 stock3 stock4
[1,] 0.01 0.00 0.00 0.00
[2,] -0.02 0.00 0.00 -0.02
[3,] 0.01 0.02 0.02 0.01
[4,] 0.05 0.04 0.00 0.00
[5,] 0.04 -0.03 -0.01 0.00
[6,] -0.02 0.02 0.03 -0.02
对于给定的股票,在非零之前的任何零表示缺少数据,而不是该期间的零返回。我想将这些值设置为NA,所以我要实现的输出如下:
所需的输出:
stock1 <- c(0.01, -0.02, 0.01, 0.05, 0.04, -0.02)
stock2 <- c(NA, NA, 0.02, 0.04, -0.03, 0.02)
stock3 <- c(NA, NA, 0.02, 0, -0.01, 0.03)
stock4 <- c(NA, -0.02, 0.01, 0, 0, -0.02)
df <- cbind(stock1,stock2,stock3,stock4)
stock1 stock2 stock3 stock4
[1,] 0.01 NA NA NA
[2,] -0.02 NA NA -0.02
[3,] 0.01 0.02 0.02 0.01
[4,] 0.05 0.04 0.00 0.00
[5,] 0.04 -0.03 -0.01 0.00
[6,] -0.02 0.02 0.03 -0.02
我已经尝试了一些方法,但是它们似乎只适用于单个向量,而不是具有多列的数据集。我尝试使用lapply来解决此问题,但到目前为止还没有任何运气。我得到的最接近的信息如下所示。
我的单个向量解决方案:
stock1[1:min(which(stock1!=0))-1 <- NA
我的多向量解决方案不起作用:
lapply(df,function(x) x[1:min(which(x!=0))-1 <- NA]
将非常感谢任何指导!谢谢!
答案 0 :(得分:7)
有三个问题。首先,写:
df <- cbind(stock1,stock2,stock3,stock4)
不创建数据框。它创建一个矩阵。当您尝试使用lapply
时,这是一个问题,它将在数据框的列上但在矩阵的元素上进行操作。相反,您应该写:
df <- data.frame(stock1,stock2,stock3,stock4)
第二,您在lapply
中使用的函数需要返回修改后的向量。否则,返回值将是意外的(在这种情况下,赋值将返回单个NA
,而lapply
将返回一行NA
的数据帧,而不是您想要的数据框)。
第三,当1:n
可以为零时(即,当第一个股票报价不为零时),您需要注意n
,因为1:0
给出了序列{{1 }},而不是一个空序列。 (可以说这是R最愚蠢的功能之一。)
因此,以下内容将为您提供所需的内容:
c(1,0)
输出符合预期:
stock1 <- c(0.01, -0.02, 0.01, 0.05, 0.04, -0.02)
stock2 <- c(0, 0, 0.02, 0.04, -0.03, 0.02)
stock3 <- c(0, 0, 0.02, 0, -0.01, 0.03)
stock4 <- c(0, -0.02, 0.01, 0, 0, -0.02)
df <- data.frame(stock1,stock2,stock3,stock4)
as.data.frame(lapply(df, function(x) {
n <- min(which(x != 0)) - 1
if (n > 0)
x[1:n] <- NA
x
}))
更新:如@Daniel_Fischer所述,有一个巧妙的技巧可以避免 stock1 stock2 stock3 stock4
1 0.01 NA NA NA
2 -0.02 NA NA -0.02
3 0.01 0.02 0.02 0.01
4 0.05 0.04 0.00 0.00
5 0.04 -0.03 -0.01 0.00
6 -0.02 0.02 0.03 -0.02
问题。您可以改为:
1:0
这利用了R在这种类型的索引操作中忽略零的事实,因此:
as.data.frame(lapply(df, function(x) {
n <- min(which(x != 0)) - 1
x[0:n] <- NA # use 0:n instead of 1:n
x
}))
答案 1 :(得分:4)
这可能不是最优雅的方法,但我认为它可行
www.example.com/api/ajax?123
www.example.com/api/ajax?1234
编辑:对该函数的一些简要说明:首先,我创建一个向量,该向量在列中为零的每个位置处增加,然后检查该向量在哪个位置处不增加(=表示不存在两个彼此相邻的零),然后我仍要取其中的最小值,并确保它们仅是前导零(这样就不会更改矩阵中的值)
答案 2 :(得分:3)
stock1 <- c(0.01, -0.02, 0.01, 0.05, 0.04, -0.02)
stock2 <- c(0, 0, 0.02, 0.04, -0.03, 0.02)
stock3 <- c(0, 0, 0.02, 0, -0.01, 0.03)
stock4 <- c(0, -0.02, 0.01, 0, 0, -0.02)
df <- data.frame(stock1,stock2,stock3,stock4) #the following function only works if df is actually a data.frame
df[] <- lapply(df, function(x) {ifelse(cumsum(x) == 0 & x == 0, NA, x)})
df
stock1 stock2 stock3 stock4
1 0.01 NA NA NA
2 -0.02 NA NA -0.02
3 0.01 0.02 0.02 0.01
4 0.05 0.04 0.00 0.00
5 0.04 -0.03 -0.01 0.00
6 -0.02 0.02 0.03 -0.02
一些解释:首先检查每个单元格的累积colSum
和当前单元格是否等于0
。如果是这样,则返回NA
,否则返回原始值。 df
后面的括号可确保lapply
函数再次返回分配给dataframe
的{{1}}。
此外,如果您真的不需要df作为数据帧,那么它也可以正常工作:
df