【问题标题】:Count consecutive strings of zeroes and ones over multiple groups计算多个组中连续的 0 和 1 字符串
【发布时间】:2014-11-20 19:38:16
【问题描述】:

关于使用 rlecumsum 之类的函数计算连续的 0 和 1(或其他值)字符串,已经有过多次讨论。我已经玩过这些功能,但我无法轻松弄清楚如何让它们应用于我的特定问题。

我正在处理按时间(“年份”)和位置(“id”)组织的生态存在/不存在数据(“pres.abs”= 1 或 0)。对于每个位置 id,我想分别计算连续 1 和 0 的长度。在这些无法计算的地方,我想返回“NA”。

下面是数据的样例(前 3 列)和我希望实现的输出(最后 2 列)。理想情况下,这将是一个非常快速的函数,可以避免 for 循环,因为实际数据帧包含约 15,000 行。

year = rep(1:10, times=3)
id = c(rep(1, times=10), rep(2, times=10), rep(3, times=10))
pres.abs.id.1 = c(0, 0, 0, 1, 1, 1, 0, 0, 1, 1) #Pres/abs data at site 1 across time
pres.abs.id.2 = c(1, 1, 0, 1, 0, 0, 1, 0, 0, 0) #Pres/abs data at site 2 across time
pres.abs.id.3 = c(0, 0, 0, 0, 0, 1, 1, 1, 1, 1) #Pres/abs data at site 3 across time
pres.abs = c(pres.abs.id.1, pres.abs.id.2, pres.abs.id.3)
dat = data.frame(id, year, pres.abs)

dat$cumul.zeroes = c(1,2,3,NA,NA,NA,1,2,NA,NA,NA,NA,1,NA,1,2,NA,1,2,3,1,2,3,4,5,NA,NA,NA,NA,NA)
dat$cumul.ones = c(NA,NA,NA,1,2,3,NA,NA,1,2,1,2,NA,1,NA,NA,1,NA,NA,NA,NA,NA,NA,NA,NA,1,2,3,4,5)

> dat
   id year pres.abs cumul.zeroes cumul.ones
1   1    1        0            1         NA
2   1    2        0            2         NA
3   1    3        0            3         NA
4   1    4        1           NA          1
5   1    5        1           NA          2
6   1    6        1           NA          3
7   1    7        0            1         NA
8   1    8        0            2         NA
9   1    9        1           NA          1
10  1   10        1           NA          2
11  2    1        1           NA          1
12  2    2        1           NA          2
13  2    3        0            1         NA
14  2    4        1           NA          1
15  2    5        0            1         NA
16  2    6        0            2         NA
17  2    7        1           NA          1
18  2    8        0            1         NA
19  2    9        0            2         NA
20  2   10        0            3         NA
21  3    1        0            1         NA
22  3    2        0            2         NA
23  3    3        0            3         NA
24  3    4        0            4         NA
25  3    5        0            5         NA
26  3    6        1           NA          1
27  3    7        1           NA          2
28  3    8        1           NA          3
29  3    9        1           NA          4
30  3   10        1           NA          5

非常感谢您的帮助。

【问题讨论】:

    标签: r count dataframe


    【解决方案1】:

    这是使用rlesequence 的基本R 方式:

    dat <- within(dat, {
        cumul.counts <- unlist(lapply(split(pres.abs, id), function(x) sequence(rle(x)$lengths)))
        cumul.zeroes <- replace(cumul.counts, pres.abs == 1, NA)
        cumul.ones <- replace(cumul.counts, pres.abs == 0, NA)
        rm(cumul.counts)
    })
    
    #    id year pres.abs cumul.ones cumul.zeroes
    # 1   1    1        0         NA            1
    # 2   1    2        0         NA            2
    # 3   1    3        0         NA            3
    # 4   1    4        1          1           NA
    # 5   1    5        1          2           NA
    # 6   1    6        1          3           NA
    # 7   1    7        0         NA            1
    # 8   1    8        0         NA            2
    # 9   1    9        1          1           NA
    # 10  1   10        1          2           NA
    # 11  2    1        1          1           NA
    # 12  2    2        1          2           NA
    # 13  2    3        0         NA            1
    # 14  2    4        1          1           NA
    # 15  2    5        0         NA            1
    # 16  2    6        0         NA            2
    # 17  2    7        1          1           NA
    # 18  2    8        0         NA            1
    # 19  2    9        0         NA            2
    # 20  2   10        0         NA            3
    # 21  3    1        0         NA            1
    # 22  3    2        0         NA            2
    # 23  3    3        0         NA            3
    # 24  3    4        0         NA            4
    # 25  3    5        0         NA            5
    # 26  3    6        1          1           NA
    # 27  3    7        1          2           NA
    # 28  3    8        1          3           NA
    # 29  3    9        1          4           NA
    # 30  3   10        1          5           NA
    

    【讨论】:

    • 太棒了!你是一个真正的巫师。非常感谢!
    【解决方案2】:

    这是 dplyr 的一个选项:

    require(dplyr)
    dat %>%
      group_by(id, x = cumsum(c(0,diff(pres.abs)) != 0)) %>%
      mutate(cumul.zeros = ifelse(pres.abs, NA_integer_, row_number()),
             cumul.ones = ifelse(!pres.abs, NA_integer_, row_number())) %>%
      ungroup() %>% select(-x) 
    
    #Source: local data frame [30 x 5]
    #
    #   id year pres.abs cumul.zeros cumul.ones
    #1   1    1        0           1         NA
    #2   1    2        0           2         NA
    #3   1    3        0           3         NA
    #4   1    4        1          NA          1
    #5   1    5        1          NA          2
    #6   1    6        1          NA          3
    #7   1    7        0           1         NA
    #8   1    8        0           2         NA
    #9   1    9        1          NA          1
    #10  1   10        1          NA          2
    #11  2    1        1          NA          1
    #12  2    2        1          NA          2
    #13  2    3        0           1         NA
    #14  2    4        1          NA          1
    #15  2    5        0           1         NA
    #16  2    6        0           2         NA
    #17  2    7        1          NA          1
    #18  2    8        0           1         NA
    #19  2    9        0           2         NA
    #20  2   10        0           3         NA
    #21  3    1        0           1         NA
    #22  3    2        0           2         NA
    #23  3    3        0           3         NA
    #24  3    4        0           4         NA
    #25  3    5        0           5         NA
    #26  3    6        1          NA          1
    #27  3    7        1          NA          2
    #28  3    8        1          NA          3
    #29  3    9        1          NA          4
    #30  3   10        1          NA          5
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多