【问题标题】:Create counter with multiple variables that restart within each subgroup创建具有在每个子组内重新启动的多个变量的计数器
【发布时间】:2016-12-08 12:27:16
【问题描述】:

我有一个包含两列(标识和值)的数据框。我想创建一个计数器,每次 ident 值更改以及每个 ident 中的值更改时都会重新启动。这里有一个例子来说明清楚。

# ident value counter
#-------------------- 
#  1     0       1
#  1     0       2
#  1     1       1
#  1     1       2
#  1     1       3
#  1     0       1
#  1     1       1
#  1     1       2
#  2     1       1
#  2     0       1
#  2     0       2
#  2     0       3

我试过 plyr 包

ddply(mydf, .(ident, value), transform, .id = seq_along(ident))

与 data.frame 包的结果相同。

【问题讨论】:

  • 这将不会处理第 7 行的 (1,1) 组的重复。它将被计为 4,5

标签: r counter multivalue


【解决方案1】:

使用rleid/rowid 函数的data.table 替代方案。使用rleid,您可以为连续值创建一个运行长度id,它可以用作一个组。 1:.Nrowid 可用于创建计数器。代码:

library(data.table)
# option 1:
setDT(d)[, counter := 1:.N, by = .(ident,rleid(value))]
# option 2:
setDT(d)[, counter := rowid(ident, rleid(value))]

两者都给出:

> d
    ident value counter
 1:     1     0       1
 2:     1     0       2
 3:     1     1       1
 4:     1     1       2
 5:     1     1       3
 6:     1     0       1
 7:     1     1       1
 8:     1     1       2
 9:     2     1       1
10:     2     0       1
11:     2     0       2
12:     2     0       3

使用dplyr 就没有那么简单了:

library(dplyr)
d %>% 
  group_by(ident, val.gr = cumsum(value != lag(value, default = first(value)))) %>% 
  mutate(counter = row_number()) %>% 
  ungroup() %>% 
  select(-val.gr)

作为cumsum 函数的替代方案,您可以从data.table 转换为also use rleid


使用过的数据:

d <- structure(list(ident = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), 
                    value = c(0L, 0L, 1L, 1L, 1L, 0L, 1L, 1L, 1L, 0L, 0L, 0L)), 
               .Names = c("ident", "value"), class = "data.frame", row.names = c(NA, -12L))

【讨论】:

    【解决方案2】:

    我们可以将paste这两个值放在一起,并使用rlelength属性来获取连续数字的长度。然后我们使用sequence 来生成计数器。

    df$counter <- sequence(rle(paste0(df$dent, df$value))$lengths)
    df
    #   dent value counter
    #1     1     0       1
    #2     1     0       2
    #3     1     1       1
    #4     1     1       2
    #5     1     1       3
    #6     1     0       1
    #7     1     1       1
    #8     1     1       2
    #9     2     1       1
    #10    2     0       1
    #11    2     0       2
    #12    2     0       3
    

    【讨论】:

      猜你喜欢
      • 2013-08-31
      • 2016-12-18
      • 1970-01-01
      • 1970-01-01
      • 2017-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多