【问题标题】:How to aggregate when there are missing time series data combination缺少时序数据组合时如何聚合
【发布时间】:2017-04-18 22:31:11
【问题描述】:

我有一个如下所示的数据集:

我想按日期聚合数据,结果应该是这样的:

我写了函数“聚合”:

## Subset data
seller <- c ("S1", "S2","S3","S4", "S5")
buyer <- c("B1", "B2", "B3", "B4", "B5")
ss <- df[seller, buyer]

但是,由于卖方-买方-食品的某些组合不存在(例如卖方 S1 和买方 B3 没有交易),所以 R 给了我错误: Error in[.default(x1, , 1:5) : subscript out of bounds

有人可以帮助我如何告诉 R 继续“聚合”功能,即使买卖双方之间没有交易。 感谢所有帮助!

【问题讨论】:

    标签: r dataframe aggregate missing-data


    【解决方案1】:

    这是您可以使用tidyrspread 做到这一点的一种方法:

    Date <- as.character(Sys.Date()+0:4)
    seller <- c ("S1", "S2","S3","S4", "S5")
    buyer <- c("B1", "B2", "B3", "B4", "B5")
    Food <- c("Coconut","Banana","Peach","Peach","Apple")
    
    df <- data.frame(cbind(Date,seller,buyer,Food),stringsAsFactors=FALSE)
    
    library(tidyr)
    df2 <- df%>%
    group_by(Date,seller,buyer)%>%
    mutate(count=n())%>%
    spread(Food,count)
    df2[is.na(df2)] <- 0
    df2
    
    Source: local data frame [5 x 7]
    Groups: Date, seller, buyer [5]
    
            Date seller buyer Apple Banana Coconut Peach
    *      <chr>  <chr> <chr> <dbl>  <dbl>   <dbl> <dbl>
    1 2017-04-18     S1    B1     0      0       1     0
    2 2017-04-19     S2    B2     0      1       0     0
    3 2017-04-20     S3    B3     0      0       0     1
    4 2017-04-21     S4    B4     0      0       0     1
    5 2017-04-22     S5    B5     1      0       0     0
    

    编辑要考虑重复,请添加summarise 步骤。数据集已被修改,使得 S1、B1、香蕉和同一日期发生。

    Date <- as.character(Sys.Date()+c(0,0,1,2,3))
    seller <- c ("S1", "S1","S3","S4", "S5")
    buyer <- c("B1", "B1", "B3", "B4", "B5")
    Food <- c("Banana","Banana","Peach","Peach","Apple")
    
    df <- data.frame(cbind(Date,seller,buyer,Food),stringsAsFactors=FALSE)
    
    library(tidyr)
    df2 <- df%>%
    group_by(Date,seller,buyer,Food)%>%
    summarise(count=n())%>%
    spread(Food,count)
    
    df2[is.na(df2)] <- 0
    df2
    
            Date seller buyer Apple Banana Peach
    *      <chr>  <chr> <chr> <dbl>  <dbl> <dbl>
    1 2017-04-19     S1    B1     0      2     0
    2 2017-04-20     S3    B3     0      0     1
    3 2017-04-21     S4    B4     0      0     1
    4 2017-04-22     S5    B5     1      0     0
    

    【讨论】:

    • 谢谢!但是您使用的“df”是您生成的数据框,而不是我从完整数据集制作的子集数据“ss”
    • @CPA 这是因为我覆盖了我原来的df。我编辑了我的答案。 df 现在是原始数据。 df2 是最后一个
    • 感谢您的回答。我的意思是您创建的第一个“df”。它只为 5 个卖家、买家和食物生成了 5 行。你能告诉我如何将 df 链接到我拥有的子集数据,我在我的代码中将其命名为“ss”(“ss”是一个大数据集的子集,我在我的代码中也将其命名为“df”,其中包括成千上万的卖家和买家,但我只想要几个特定的​​卖家和买家)
    • 更新:我已成功链接到我的数据集。但是,R 给了我 Error: Duplicate identifiers for rows 因为有很多重复的事务(例如,S1-B1-Banana 事务每天可能发生多次,导致几个相似的行)。并且“日期”会根据当前日期而不是我的数据集中的日期生成。有什么建议吗?
    • @P Lapointe 代码运行良好。但仅适用于每天单一的卖方-买方-食品交易。但是,当卖方-买方每天有一些交易时,计算是不正确的。例如,如果 S1 在 2017 年 1 月 1 日两次向 B1 出售香蕉,结果是 4 笔交易而不是 2 笔。我猜原因是“summarise(count=sum(count))”但不知道解决那个。你能帮忙吗?
    【解决方案2】:

    reshape2data.table 包中的 dcast() 函数可以方便地将您的数据从长格式转换为宽格式:

    data.table::dcast(ss, ... ~ Food, value.var = "Food", fill = 0L, fun = length)
    #        Date seller buyer Apple Banana Coconut Peach
    #1 2017-01-01     S1    B1     0      0       1     0
    #2 2017-01-01     S2    B1     0      1       0     0
    #3 2017-01-02     S2    B3     0      0       0     1
    #4 2017-01-03     S3    B1     0      0       0     1
    #5 2017-01-03     S3    B2     1      0       0     0
    #6 2017-01-03     S4    B3     0      0       1     0
    

    这也适用于重复条目,如对dplyr / tidyr solution 的编辑示例数据。

    基准测试结果

    即使对于只有 6 行的 data.frame ssdcast() 的速度也是 dplyr / tidyr 解决方案的两倍多:

    Unit: milliseconds
       expr      min       lq     mean   median       uq      max neval
     tidyr2 4.765453 4.911954 5.140440 5.011259 5.163234 6.853099   100
      dcast 1.934349 2.004580 2.102577 2.061972 2.122196 3.507352   100 
    

    基准代码

    Date <- as.Date("2017-01-01") + c(0L, 0L, 1L, 2L, 2L, 2L)
    seller <- c ("S1", "S2", "S2", "S3","S3", "S4")
    buyer <- c("B1", "B1", "B3", "B1", "B2", "B3")
    Food <- c("Coconut", "Banana", "Peach", "Peach", "Apple", "Coconut")
    ss <- data.frame(Date, seller, buyer, Food, stringsAsFactors = FALSE)
    
    library(magrittr)
    microbenchmark::microbenchmark(
      tidyr2 = {
        df2 <- ss%>%
          dplyr::group_by(Date,seller,buyer)%>%
          dplyr::mutate(count=n())%>%
          dplyr::group_by(Date,seller,buyer,Food)  %>%
          dplyr::summarise(count=sum(count))  %>%
          tidyr::spread(Food,count)
        df2[is.na(df2)] <- 0
        df2
      },
      dcast = {
        data.table::dcast(ss, ... ~ Food, value.var = "Food", fill = 0L, fun = length)
      }
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-25
      • 1970-01-01
      • 2019-12-10
      • 2020-08-22
      • 1970-01-01
      • 2019-09-21
      • 2021-07-22
      • 1970-01-01
      相关资源
      最近更新 更多