如何使用R data.table将值从一行和一列(“单元格”)复制(“继承”)到另一行和一列?

时间:2018-10-11 19:06:54

标签: r data.table

我有一个R data.table。我想基于key将值从一列和一行复制或转发到另一列和一行。我已经使用mergerbindlist完成了此操作,但我想知道是否还有更简化的解决方案。

这是一个玩具示例:假设我要跟踪不同日期的不同支票帐户的期初和期末余额。我想结转前一天(t-1)的当日余额到当日(t)的当期余额。

输入以下内容:

> DT_in <- data.table(date = c("2017-12-29", "2017-12-29", "2017-12-29", "2018-01-02", 
+                         "2018-01-02", "2018-01-02", "2018-01-02", "2018-01-03", 
+                         "2018-01-03", "2018-01-03", "2018-01-03"), 
+                  account_id = c("A17", "A23", "B21", "A17", "A23", "B21", "C12", 
+                                 "A17", "A23", "B21", "C12"),
+                  opening_balance = NA,
+                  ending_balance = c(224, 254, 240, 290, 107, 272, 105, 256, 215, 
+                                     202, 238)
+                  )
> DT_in
          date account_id opening_balance ending_balance
 1: 2017-12-29        A17              NA            224
 2: 2017-12-29        A23              NA            254
 3: 2017-12-29        B21              NA            240
 4: 2018-01-02        A17              NA            290
 5: 2018-01-02        A23              NA            107
 6: 2018-01-02        B21              NA            272
 7: 2018-01-02        C12              NA            105
 8: 2018-01-03        A17              NA            256
 9: 2018-01-03        A23              NA            215
10: 2018-01-03        B21              NA            202
11: 2018-01-03        C12              NA            238

想要此输出:

> DT_out <- data.table(date = c("2017-12-29", "2017-12-29", "2017-12-29", "2018-01-02", 
+                           "2018-01-02", "2018-01-02", "2018-01-02", "2018-01-03", 
+                           "2018-01-03", "2018-01-03", "2018-01-03"), 
+                  account_id = c("A17", "A23", "B21", "A17", "A23", "B21", "C12", 
+                                 "A17", "A23", "B21", "C12"),
+                  opening_balance = c(NA, NA, NA, 224, 254, 240, NA, 290, 107, 272, 105), 
+                  ending_balance = c(224, 254, 240, 290, 107, 272, 105, 256, 215, 
+                                     202, 238)
+                  )
> DT_out
          date account_id opening_balance ending_balance
 1: 2017-12-29        A17              NA            224
 2: 2017-12-29        A23              NA            254
 3: 2017-12-29        B21              NA            240
 4: 2018-01-02        A17             224            290
 5: 2018-01-02        A23             254            107
 6: 2018-01-02        B21             240            272
 7: 2018-01-02        C12              NA            105
 8: 2018-01-03        A17             290            256
 9: 2018-01-03        A23             107            215
10: 2018-01-03        B21             272            202
11: 2018-01-03        C12             105            238

请注意,account_id不一定从一个日期到下一个日期都是永久的(可以添加新日期,也可以删除旧日期)。没关系,但是请注意,日期是营业日期,而不是日历日期。

1 个答案:

答案 0 :(得分:3)

如果您修复示例数据以通过以下方式使用“ opening_balance”和“ ending_balance”列的相同数据类型

...
opening_balance = NA_real_,
...

您可以使用此代码将每组的最后一个观察结转(应用正确的顺序/对行进行排序之后!):

setorder(DT_in, account_id, date)
DT_in[, opening_balance := shift(ending_balance, 1), by = .(account_id)]

这导致(排序的输出):

> DT_in
          date account_id opening_balance ending_balance
 1: 2017-12-29        A17              NA            224
 2: 2018-01-02        A17             224            290
 3: 2018-01-03        A17             290            256
 4: 2017-12-29        A23              NA            254
 5: 2018-01-02        A23             254            107
 6: 2018-01-03        A23             107            215
 7: 2017-12-29        B21              NA            240
 8: 2018-01-02        B21             240            272
 9: 2018-01-03        B21             272            202
10: 2018-01-02        C12              NA            105
11: 2018-01-03        C12             105            238