R:在时间相关数据帧中查找并添加缺失(/非现有)行

时间:2012-04-03 15:24:38

标签: r

我正在努力解决以下问题。

如果有一个(大)数据框,则包含以下内容:

  • 多列,其中列的组合是唯一的'组合,比如说ID
  • 与时间相关的专栏
  • 与度量相关的列

我想确保对于每个时间间隔的每个唯一ID,数据框中都有一个度量值。如果不是,我想为该时间/ ID添加0(或NA)度量。

要说明问题,请创建以下test数据框:

test <- data.frame(
    YearWeek   =rep(c("2012-01","2012-02"),each=4),
    ProductID  =rep(c(1,2), times=4),
    CustomerID =rep(c("a","b"), each=2, times=2),
    Quantity   =5:12
)[1:7,]

  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11

故意排除第8行。通过这种方式,我模拟了一个“缺失值”&#39; (缺少Quantity)ID&#39; 2-b&#39; (ProductID-CustomerID)了解时间价值&#34; 2012-02&#34;。

我想要做的是调整data.frame,以便对所有时间值(这些都是已知的,在这个例子中只是&#34; 2012-01&#34;&#34; 2012-02& #34;),对于所有ID组合(这些都是预先知道的,但这是数据框中的所有唯一ID组合&#39;,因此ID列上的唯一ID),数量可用在数据框中。

这应该是这个例子的结果(如果我们为缺失的值选择NA,通常我想控制它):

  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11
8  2012-02         2          b       NA

最终目标是为这些ID组合创建时间序列,因此我希望拥有所有时间值的数量。我需要进行不同的聚合(按时)并使用来自大数据集的不同级别的ID

我尝试了几件事,例如melt包中的castreshape。但到目前为止,我没有设法做到这一点。下一步是使用for循环等创建一个函数,但从性能角度来看这并不是很有用。

也许有一种更简单的方法可以立即创建时间序列,提供像test这样的数据框架。有没有人对这个有想法?

提前致谢!

请注意,在实际问题中,有两个以上的ID列&#39;。


编辑:

我应该进一步描述这个问题。 “时间”与“时间”之间存在差异。栏目和“ID&#39;列。关于 joran 这个问题的第一个(也是伟大的!)答案,也许并没有从我想要的东西中得到清楚的理解(我给出的例子并没有明确区别)。我上面说过:

  

所有ID组合(这些都是前期未知的,但这是全部   数据框中的唯一ID组合&#39;,因此唯一的ID集合   ID列)

所以我不想要所有可能的ID组合&#39;但是&#39;数据中的所有ID组合&#39;。 对于每个组合,我想要每个唯一时间值的值。

让我通过将test扩展为test2来明确说明,如下所示

> test2 <- rbind(test, c("2012-02", 3, "a", 13))
> test2
  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         2          a        6
3  2012-01         1          b        7
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         2          a       10
7  2012-02         1          b       11
8  2012-02         3          a       13

这意味着我想在结果数据框中没有&#39; 3-b&#39; ID组合,因为此组合不在test2范围内。如果我使用第一个答案的方法,我将得到以下内容:

> vals2 <- expand.grid(YearWeek = unique(test2$YearWeek),
                       ProductID = unique(test2$ProductID),
                       CustomerID = unique(test2$CustomerID))

> merge(vals2,test2,all = TRUE)
   YearWeek ProductID CustomerID Quantity
1   2012-01         1          a        5
2   2012-01         1          b        7
3   2012-01         2          a        6
4   2012-01         2          b        8
5   2012-01         3          a     <NA>
6   2012-01         3          b     <NA>
7   2012-02         1          a        9
8   2012-02         1          b       11
9   2012-02         2          a       10
10  2012-02         2          b     <NA>
11  2012-02         3          a       13
12  2012-02         3          b     <NA>

所以我不希望行612在这里。

为了克服这个问题,我在下面找到了一个解决方案。在这里,我拆分了独特的时间列&#39;和唯一的ID组合&#39;。因此,与上面的区别在于“组合”这个词。并非每个ID列都是唯一的。

> temp_merge <- merge(unique(test2["YearWeek"]),
                      unique(test2[c("ProductID", "CustomerID")]))

> merge(temp_merge,test2,all = TRUE)
   YearWeek ProductID CustomerID Quantity
1   2012-01         1          a        5
2   2012-01         1          b        7
3   2012-01         2          a        6
4   2012-01         2          b        8
5   2012-01         3          a     <NA>
6   2012-02         1          a        9
7   2012-02         1          b       11
8   2012-02         2          a       10
9   2012-02         2          b     <NA>
10  2012-02         3          a       13

对此有何评论?

这是一种优雅的方式,还是有更好的方法?

1 个答案:

答案 0 :(得分:20)

使用expand.gridmerge

vals <- expand.grid(YearWeek = unique(test$YearWeek),
                    ProductID = unique(test$ProductID),
                    CustomerID = unique(test$CustomerID))
> merge(vals,test,all = TRUE)
  YearWeek ProductID CustomerID Quantity
1  2012-01         1          a        5
2  2012-01         1          b        7
3  2012-01         2          a        6
4  2012-01         2          b        8
5  2012-02         1          a        9
6  2012-02         1          b       11
7  2012-02         2          a       10
8  2012-02         2          b       NA

NA可以在事实之后使用子集和is.na替换您选择的任何值。