【问题标题】:count the length of Number Sequences计算数列的长度
【发布时间】:2016-08-11 23:22:09
【问题描述】:

包含一些算术序列 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 提出解决方案?

【问题讨论】:

标签: r data.table dplyr


【解决方案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))]

【讨论】:

  • 我收到了 Error: expecting a single valuedplyr 解决方案。我想我错过了什么。
  • @user 它适用于我给出的示例(dplyr 0.5,r 3.2.4)。我不知道为什么会出现这个错误,因为它通常是由summarise 触发的,这里没有出现。
  • 我有dplyr ‘0.4.3’ &amp; R 3.2.5。可能是因为版本问题。
  • data.table 解决方案看起来非常不错。貌似你用cumsum来实现rle的功能?它更快吗?
  • @Dong 我猜cumsumrle 不能在这里替代。例如,如果x=c(1,2,3,5,7) 正确的索引应该是c(1,2,3,1,1),但如果你使用rleid(x != shift(x, fill=x[1L]-1L) + 1L) 之类的东西,你会得到c(1,2,3,1,2)
【解决方案2】:

另一个使用base R的选项

unlist(sapply(rle(cumsum(ifelse(diff(c(df$x[1],df$x))!=1,1,0)))$lengths,seq_len))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-10
    • 2011-08-07
    • 2015-05-09
    • 1970-01-01
    • 2018-10-10
    • 2017-03-04
    相关资源
    最近更新 更多