【问题标题】:Expand Data Frame展开数据框
【发布时间】:2016-02-29 20:21:13
【问题描述】:

我想在某些条件下扩展数据框。有点像这个问题expand data frames inside data frame,但又不太一样。

我有一个数据框:

df = data.frame(ID = c(3,3,3,3, 17,17,17, 74, 74, 210, 210, 210, 210), amount = c(101, 135, 101, 68,  196, 65 ,135, 76, 136, 15, 15, 15 ,15), week.number = c(4, 6, 8, 10, 2, 5, 7, 2, 6, 2, 3, 5, 6))

我想扩展每个 ID 的数据框,给定一个最小和最大周数,并在此扩展的数量列中具有 0。最小周数为 1,最大周数为 10。预期结果为:

df1 <- data.frame(ID = c(rep(3,10), rep(17, 10), rep(74, 10), rep(210, 10)),
              amount = c(0, 0, 0, 101, 0, 135, 0, 101, 0, 68, 0, 196,
                         0, 0, 65, 0, 135, 0, 0, 0, 0, 76, 0, 0, 0,
                         136, 0, 0, 0, 0, 0, 15, 15, 0, 15, 15, 0, 0,
                         0, 0))

(实际上,我有数千个 ID,周数从 1 到 160)。

有没有一种简单、快速的方法来做到这一点?

谢谢!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    使用data.table(发送给 Frank 以纠正结果的长度):

    require(data.table)
    dt<-as.data.table(df)
    f<-function(x,y,len=max(y)) {res<-numeric(len);res[y]<-x;res}
    dt[,list(amount=f(amount,weeek.number,10)),by=ID]
    #     ID amount
    # 1:   3      0
    # 2:   3      0
    # 3:   3      0
    # 4:   3    101
    # 5:   3      0
    # 6:   3    135
    # 7:   3      0
    # 8:   3    101
    # 9:   3      0
    #10:   3     68
    # ......
    

    编辑

    我刚刚注意到您的amountweeek.number 实际上定义了一个sparseVector,即主要由零组成的向量,其中仅保留非零元素的索引。所以,你可以试试Matrix 包:

    require(Matrix)
    dt[,list(as.vector(sparseVector(amount,weeek.number,10))),by=ID]
    

    得到与上面相同的结果。

    【讨论】:

    • 你说得对,我要进行编辑。发送通知。
    • 谢谢!两种解决方案都非常优雅。我认为,就我而言, sparseVector 更有用,因为我将有更多列在扩展数据框时应保持不变。再次感谢!
    【解决方案2】:

    以下是使用tidyr 的方法:

    library(tidyr)
    complete(df, ID, weeek.number = 1:10, fill = list(amount = 0))
    #Source: local data frame [40 x 3]
    #
    #      ID weeek.number amount
    #   (dbl)        (dbl)  (dbl)
    #1      3            1      0
    #2      3            2      0
    #3      3            3      0
    #4      3            4    101
    #5      3            5      0
    #6      3            6    135
    #7      3            7      0
    #8      3            8    101
    #9      3            9      0
    #10     3           10     68
    #..   ...          ...    ...
    

    base R 中的一种方法是使用expand.gridmerge

    newdf <- merge(expand.grid(ID = unique(df$ID), weeek.number = 1:10), df, all.x = TRUE)
    newdf$amount[is.na(newdf$amount)] <- 0   # replace NA with 0
    

    【讨论】:

    • 谢谢!虽然,使用 tidyr 包时出现错误:错误:位置必须介于 0 和 n 之间。将进一步调查。
    • @Andres,你有最新的 tidyr 版本吗? (0.4.1)
    • 我的第一个想法。是的,也就是说,我有 0.3.1。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多