2017-01-26 61 views
2

我有一个类似于以下内容的数据表。请注意,当vals0时,该标志为1,并在其他地方丢失。使用R数据中的序列填充NA值

dt <- data.table(vals = c(0,2,4,1,0,4,3,0,3,4)) 
dt[vals == 0, flag := 1] 

> dt 
    vals flag 
1: 0 1 
2: 2 NA 
3: 4 NA 
4: 1 NA 
5: 0 1 
6: 4 NA 
7: 3 NA 
8: 0 1 
9: 3 NA 
10: 4 NA 

我想输出看起来像下面的seq列。也就是说,该列需要包含从1开始的一组序列,每当vals0并且当vals0时计数直到下一行。 flag只有在帮助实现所述目标时才有用。

> dt 
    vals seq 
1: 0 1 
2: 2 2 
3: 4 3 
4: 1 4 
5: 0 1 
6: 4 2 
7: 3 3 
8: 0 1 
9: 3 3 
10: 4 3 

本来,我想使用cumsum()莫名其妙,但我无法弄清楚如何有效地使用它。

我目前的解决方案非常难看。

dt <- data.table(vals = c(0,2,4,1,0,4,3,0,3,4)) 
dt[vals == 0, flag := 1] 
dt[, flag_rleid := rleid(flag)] 

# group on the flag_rleid column 
dt[, flag_seq := seq_len(.N), by = flag_rleid] 
# hideous subsetting to avoid incrementing the first appearance of a 1 
dt[vals != 0, flag_seq := flag_seq + 1] 

# flag_seq is the desired column 
> dt 
    vals flag flag_rleid flag_seq 
1: 0 1   1  1 
2: 2 NA   2  2 
3: 4 NA   2  3 
4: 1 NA   2  4 
5: 0 1   3  1 
6: 4 NA   4  2 
7: 3 NA   4  3 
8: 0 1   5  1 
9: 3 NA   6  2 
10: 4 NA   6  3 

任何改进的赞赏。

回答

2

我们可以用一个逻辑索引与cumsum创建分组变量,然后根据我们得到的序列科拉姆

dt[, flag_seq := seq_len(.N), cumsum(vals ==0)] 
dt 
# vals flag flag_seq 
# 1: 0 1  1 
# 2: 2 NA  2 
# 3: 4 NA  3 
# 4: 1 NA  4 
# 5: 0 1  1 
# 6: 4 NA  2 
# 7: 3 NA  3 
# 8: 0 1  1 
# 9: 3 NA  2 
#10: 4 NA  3