计算R中每组连续连续值的长度

时间:2021-02-04 14:33:06

标签: r count data.table grouping

我有一个包含连续值的数据集,我想知道每个长度出现的次数。 更具体地说,我想找出有多少 id 的序列从 1:2、1:3、1:4 等开始。 只有从 1 开始的序列才有意义。

在这个例子中,id1 有一个从 1:3 开始运行的“完整”序列(因为数字 4 缺失),id2 有一个从 1:5 开始运行的序列,id3 有一个从 1:6 开始运行的序列,id4不计算在内,因为它不是以 1 的值开始,并且 id 5 的序列从 1:3 开始。

所以我们最终得到两个序列直到 3,一个直到 5,一个直到 6。

有没有一种聪明的方法来计算这个,而不诉诸低效循环?

示例数据:

data <- data.table( id    = c(1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5),
                    value = c(1,2,3,5,1,2,3,4,5,10,11,1,2,3,4,5,6,2,3,4,5,6,7,8,1,2,3,7))

 > data
    id value
 1:  1     1
 2:  1     2
 3:  1     3
 4:  1     5
 5:  2     1
 6:  2     2
 7:  2     3
 8:  2     4
 9:  2     5
10:  2    10
11:  2    11
12:  3     1
13:  3     2
14:  3     3
15:  3     4
16:  3     5
17:  3     6
18:  4     2
19:  4     3
20:  4     4
21:  4     5
22:  4     6
23:  4     7
24:  4     8
25:  5     1
26:  5     2
27:  5     3
28:  5     7
    id value

4 个答案:

答案 0 :(得分:3)

out <- data[, len0 := rleid(c(TRUE, diff(value) == 1L)), by = .(id) ][
  , .(value1 = first(value), len = .N), by = .(id, len0) ]
out
#       id  len0 value1   len
#    <num> <int>  <num> <int>
# 1:     1     1      1     3
# 2:     1     2      5     1
# 3:     2     1      1     5
# 4:     2     2     10     1
# 5:     2     3     11     1
# 6:     3     1      1     6
# 7:     4     1      2     7
# 8:     5     1      1     3
# 9:     5     2      7     1

演练:

  • 在每个 id 中,创建 len0 以标识增加 1 的步骤
  • id,len0 内,总结第一个值(如果您只想要那些从 1 开始的值,见下文)和运行的 length

如果您只想知道序列以 1 开始的那些,请按 value1 过滤:

out[ value1 == 1L, ]
#       id  len0 value1   len
#    <num> <int>  <num> <int>
# 1:     1     1      1     3
# 2:     2     1      1     5
# 3:     3     1      1     6
# 4:     5     1      1     3

(我认为此时您只需要 idlen。)

答案 1 :(得分:3)

这是另一种选择:

data[rowid(id)==value, max(value), id]

输出:

   id V1
1:  1  3
2:  2  5
3:  3  6
4:  5  3

答案 2 :(得分:2)

使用 dplyr 的一个选项可能是:

data %>%
 group_by(id) %>%
 mutate(rleid = with(rle(c(0, diff(value)) <= 1), rep(seq_along(values), lengths))) %>%
 filter(rleid == 1 & min(value) == 1) %>%
 summarise(value = paste(value, collapse = "")) %>%
 group_by(value) %>%
 summarise(n = n(),
           ids = toString(id))

  value      n ids  
  <chr>  <int> <chr>
1 123        2 1, 5 
2 12345      1 2    
3 123456     1 3    

答案 3 :(得分:2)

library(data.table)
dt <- data.table( id    = c(1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5),
                    value = c(1,2,3,5,1,2,3,4,5,10,11,1,2,3,4,5,6,2,3,4,5,6,7,8,1,2,3,7))

dt[, n := seq_len(.N) - value, by = id]
res <- dt[n == 0, .SD[value == max(value)], by = id][, n := NULL]
head(res)
#>    id value
#> 1:  1     3
#> 2:  2     5
#> 3:  3     6
#> 4:  5     3

reprex package (v1.0.0) 于 2021 年 2 月 4 日创建