【问题标题】:Filling in values without a loop在没有循环的情况下填充值
【发布时间】:2015-12-02 23:57:41
【问题描述】:

我有一个大型数据框 x,其中包含特定日期的股票价格。我想将此数据集与日期变量合并,并填写 x 的最后已知观测值,直到下一个特定日期,以便获得数据框 z。下面的示例显示了一只股票。

我正在使用循环,但这个过程非常缓慢,因为我有五到十年的日常数据和数千只股票。

还有其他方法吗?在 Matlab 中,同样的代码运行得更快。

重要的是,除了简单的 is.na(z[t,2]==TRUE 条件之外,我还可以使用其他条件。

示例如下:

> x=data.frame(c("2015-05-31","2015-06-30","2015-07-31"),c(100,200,150))
> colnames(x)=c("Date","AAPL")
> x[,1]=as.Date(x[,1],origin="1970-01-01")
> 
> x
        Date AAPL
1 2015-05-31  100
2 2015-06-30  200
3 2015-07-31  150
> 
> date=data.frame(c("2015-05-31","2015-06-01","2015-06-02","2015-06-03","2015-06-04","2015-06-05","2015-06-06","2015-06-07","2015-06-08","2015-06-09","2015-06-10","2015-06-11","2015-06-12","2015-06-13","2015-06-14","2015-06-15","2015-06-16","2015-06-17","2015-06-18","2015-06-19","2015-06-20","2015-06-21","2015-06-22","2015-06-23","2015-06-24","2015-06-25","2015-06-26","2015-06-27","2015-06-28","2015-06-29","2015-06-30","2015-07-01","2015-07-02","2015-07-03","2015-07-04","2015-07-05","2015-07-06","2015-07-07","2015-07-08","2015-07-09","2015-07-10","2015-07-11","2015-07-12","2015-07-13","2015-07-14","2015-07-15","2015-07-16","2015-07-17","2015-07-18","2015-07-19","2015-07-20","2015-07-21","2015-07-22","2015-07-23","2015-07-24","2015-07-25","2015-07-26","2015-07-27","2015-07-28","2015-07-29","2015-07-30","2015-07-31"))
> colnames(date)=c("Date")
> date[,1]=as.Date(date[,1],origin="1970-01-01")
> 
> date
         Date
1  2015-05-31
2  2015-06-01
3  2015-06-02
29 ...
30 2015-06-29
31 2015-06-30
32 2015-07-01
33 2015-07-02

> 
> z=merge(x=x, y=date, by.x="Date", by.y="Date",all.y=TRUE)
> 
> 
> #Converting x to a data matrix speeds up the loop
> z=data.matrix(z) 
> 
> for (t in 1:nrow(z)) {
+   if (is.na(z[t,2]==TRUE)){
+     z[t,2]=z[t-1,2]
+   } else if (is.na(z[t,2]==TRUE)){
+     z[t,2]=z[t,2]
+   }
+ }
> 
> z=as.data.frame(z)
> z[,1]=as.Date(z[,1],origin="1970-01-01")
> 
> z
         Date AAPL
1  2015-05-31  100
2  2015-06-01  100
3  2015-06-02  100
29 ...
30 2015-06-29  100
31 2015-06-30  200
32 2015-07-01  200
33 2015-07-02  200

【问题讨论】:

    标签: r loops merge dataframe


    【解决方案1】:

    使用 dplyr 和 zoo 包对我有用:

    library(dplyr)
    library(zoo)
    
    my_new_df <-
      right_join(x, date) %>% 
      mutate(y = na.locf(AAPL))
    
    head(my_new_df)
    
            Date AAPL   y
    1 2015-05-31  100 100
    2 2015-06-01   NA 100
    3 2015-06-02   NA 100
    4 2015-06-03   NA 100
    5 2015-06-04   NA 100
    6 2015-06-05   NA 100
    
    tail(my_new_df)
    
             Date AAPL   y
    57 2015-07-26   NA 200
    58 2015-07-27   NA 200
    59 2015-07-28   NA 200
    60 2015-07-29   NA 200
    61 2015-07-30   NA 200
    62 2015-07-31  150 150
    

    【讨论】:

    • 感谢您的回答。是否还有一个基本的 R 方法?正如我在我的问题中所写,最好不仅使用 is.na(z[t,2]==TRUE 条件,而且还可以使用对另一个日期变量的引用(例如:如果日期仅结转值是星期三)。
    【解决方案2】:

    我们可以使用base R 来执行此操作。我们得到非 NA 'AAPL' 元素 ('i1') 的逻辑索引,cumsum 将 'i1' 转换为 numeric 索引,用它来用非 NA 元素替换 NA 元素。

    i1 <- !is.na(z$AAPL)
    z$AAPL <- z$AAPL[i1][cumsum(i1)]
    head(z)
    #        Date AAPL
    #1 2015-05-31  100
    #2 2015-06-01  100
    #3 2015-06-02  100
    #4 2015-06-03  100
    #5 2015-06-04  100
    #6 2015-06-05  100
     tail(z)
    #         Date AAPL
    #57 2015-07-26  200
    #58 2015-07-27  200
    #59 2015-07-28  200
    #60 2015-07-29  200
    #61 2015-07-30  200
    #62 2015-07-31  150
    

    【讨论】:

    • 我更喜欢这个解决方案,因为它速度快,而且它使用基础 R。这里介绍的其他解决方案也可能有效。非常感谢您的帖子!
    【解决方案3】:

    您可以尝试简洁的data.table 解决方案(而且速度很快):

    library(data.table)
    setkey(setDT(x),Date)[setDT(date), roll=T]
    

    【讨论】:

      【解决方案4】:

      如果您决定使用时间序列,例如zoo 那么这可以通过 zoo 包中的 na.locf 轻松完成。这是一些info。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-19
        • 1970-01-01
        • 2022-11-22
        • 1970-01-01
        相关资源
        最近更新 更多