计算数字序列的长度

时间:2016-08-11 23:22:10

标签: r data.table dplyr

包含一些算术序列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

这是要走的路吗?请使用dplyrdata.table建议解决方案?

2 个答案:

答案 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))