包含一些算术序列c(4,5,6)和c(10,11)的样本数据。
df <- data.frame(x = c(2, 4, 5, 6, 8, 10, 11))
我想要的是一个计算每个序列长度的新列,例如
> df
x cnt
1 2 1
2 4 1
3 5 2
4 6 3
5 8 1
6 10 1
7 11 2
首先分配df$cnt[1] = 1
,然后在第二行及以后只是增加计数,或重置为1
,这取决于df $ x中的连续数字是否符合某些标准(这里x[i] - x[i-1] == 1
)。我只是不确定循环是进入R
的方式 - 我也需要处理群组。
我可以创建新列以检查它是否在序列中。从那里,我可能会使用rle
来计算游程长度并生成cnt
列(不确定如何使用NA
)。
> df %>% mutate(check=(x-lag(x)==1))
x check
1 2 NA
2 4 FALSE
3 5 TRUE
4 6 TRUE
5 8 FALSE
6 10 FALSE
7 11 TRUE
这是要走的路吗?请使用dplyr
或data.table
建议解决方案?
答案 0 :(得分:1)
dplyr。设置default
值,它会起作用:
df %>% mutate(check = x - lag(x, default = x[1L]) != 1) %>%
group_by(g = cumsum(check)) %>%
mutate(cnt = row_number()) %>%
ungroup %>% select(-g,-check)
x cnt
<dbl> <int>
1 2 1
2 4 1
3 5 2
4 6 3
5 8 1
6 10 1
7 11 2
data.table。沿着相同的路线,更简洁:
library(data.table)
setDT(df)
df[, cnt := 1:.N, by=cumsum(x != shift(x, fill=x[1L]) + 1L)]
x cnt
1: 2 1
2: 4 1
3: 5 2
4: 6 3
5: 8 1
6: 10 1
7: 11 2
shift
是data.table,与lag
类似。
或者,从该软件包的v1.9.7开始,您可以使用rowid
代替:
df[, cnt := rowid(cumsum(x != shift(x, fill=x[1L]) + 1L))]
答案 1 :(得分:1)
使用base R
unlist(sapply(rle(cumsum(ifelse(diff(c(df$x[1],df$x))!=1,1,0)))$lengths,seq_len))