使用其前任更新列值

时间:2017-10-05 15:59:50

标签: r dplyr data.table

考虑测试数据集

 test = data.table("a"=c(NA,NA, 0, NA, NA), "b"=c(1,3,4,7,8), "c"=c(NA, 2,1,3,1), "group"=c(1,1,1,1,1))
    a  b c  group
 1: NA 1 NA 1
 2: NA 3  2 1
 3:  0 4  1 1
 4: NA 7  3 1
 5:  0 8  1 1
 6: NA 9  1 1

我想更新列的值,以便:

  t = a_{i-1}+c_i
  if(is.na(a_i)) {
    a_i = t       
  }

这应该会产生以下数据集:

    a  b c  group
 1: NA 1 NA 1
 2: NA 3  2 1
 3:  0 4  1 1
 4:  3 7  3 1
 5:  0 8  1 1
 6:  1 9  1 1

我将示例缩减为一组,但可以有多个。我宁愿避免使用循环解决方案,因为我的实际数据集有数百万行。

1 个答案:

答案 0 :(得分:0)

当我在第一个非NA NA之前有a值时,我不清楚逻辑是什么。我认为它是保持a的当前值。在这种情况下,那么这可能是你期待的:

> library(zoo)
> test = data.table("a"=c(NA,NA, 0, NA, NA, 1, 2), 
+                   "b"=c(1,3,4,7,8, 9, 10), 
+                   "c"=c(NA, 2,1,3,1, 1, 2), 
+                   "group"=c(1,1,1,1,1,1, 1))
> test
    a  b  c group
1: NA  1 NA     1
2: NA  3  2     1
3:  0  4  1     1
4: NA  7  3     1
5: NA  8  1     1
6:  1  9  1     1
7:  2 10  2     1
> 
> test[, `:=`(tmp_idx = shift(cumsum(!is.na(a)), fill = 0) > 0)][
+   , c_cum := cumsum(c), by = tmp_idx][
+     tmp_idx == 0, c_cum := 0][
+       tmp_idx == TRUE, a := NA][
+         , a := na.locf(a, na.rm = FALSE)]
> test
    a  b  c group tmp_idx c_cum
1: NA  1 NA     1   FALSE     0
2: NA  3  2     1   FALSE     0
3:  0  4  1     1   FALSE     0
4:  0  7  3     1    TRUE     3
5:  0  8  1     1    TRUE     4
6:  0  9  1     1    TRUE     5
7:  0 10  2     1    TRUE     7
> 
> test[, a := ifelse(is.na(shift(a)), a, shift(a)) + c_cum][
+   , `:=`(tmp_idx = NULL, c_cum = NULL)]
> test
    a  b  c group
1: NA  1 NA     1
2: NA  3  2     1
3:  0  4  1     1
4:  3  7  3     1
5:  4  8  1     1
6:  5  9  1     1
7:  7 10  2     1

如果您有更多群组,请使用.SD调用[.data.table内的by使用上述内容。