2016-08-11 72 views
1

样本数据包含一些算术序列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建议解决方案?

+0

密切相关的另一种选择 - [RLE般的功能捕获相邻整数的运行](http://stackoverflow.com/q/8466807/903061) – Gregor

回答

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))] 
+0

我得到'错误:期待** dplyr **解决方案的单个值。我想我错过了一些东西。 – user2100721

+0

@user它适用于我给出的例子(dplyr 0.5,r 3.2.4)。我不知道为什么会出现这种错误,因为它通常是由'summarise'触发的,它不会出现在这里。 – Frank

+0

我有'dplyr'0.4.3'&R 3.2.5'。也许我得到这个错误,由于版本。 – user2100721

1

使用base R

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