R 行的条件分组和组的编号

R conditional grouping of rows and numbering of groups

我使用飞行运动数据框(约 100 万行 * 108 个变量)并希望对满足特定标准(即特定变量的值)的阶段进行分组。为了识别这些组,我想给它们编号。 作为 R 新手,我让它适用于我的情况。现在我正在寻找一种更优雅的方式。特别是,我想克服组编号中的 "useless" 差距。 我提供了我的 dplyr 数据框的简化示例,其中阈值标准的值为 THR。这些行按时间戳排序(因此,我可以在此处截断它)。

THR <- c(13,17,19,22,21,19,17,12,12,17,20,20,20,17,17,13, 20,20,17,13)
df  <- as.data.frame(THR)
df  <- tbl_df(df)

标记所有符合(不)标准的行

df  <- mutate(df, CRIT = THR < 19)

通过以下,我设法有条件地 "cumsum" 获得了唯一的组标识:

df <- mutate(df, GRP = ifelse(CRIT == 1, 0, cumsum(CRIT))
df
    x CRIT GRP
1  13 TRUE   0
2  17 TRUE   0
3  19 FALSE  2          
4  22 FALSE  2
5  21 FALSE  2
6  19 FALSE  2
7  17 TRUE   0
8  12 TRUE   0
9  12 TRUE   0
10 17 TRUE   0
11 20 FALSE  6
12 20 FALSE  6

虽然这可以解决问题,而且我可以使用 group_by 对组进行操作(例如汇总、筛选),但从示例输出中可以看出,编号并不理想。在本例中,第 1 组编号为 2,第 2 组编号为 6,这与 cumsum() 结果一致。

如果有人能对我有所启发,我将不胜感激。我无法在其他帖子中找到合适的解决方案。

你可以这样做:

 x = rle(df$CRIT)
 mask = x$values
 x$values[mask] = 0
 x$values[!mask] = cumsum(!x$values[!mask])

 mutate(df, GRP=inverse.rle(x))

#   THR  CRIT GRP
#1   13  TRUE   0
#2   17  TRUE   0
#3   19 FALSE   1
#4   22 FALSE   1
#5   21 FALSE   1
#6   19 FALSE   1
#7   17  TRUE   0
#8   12  TRUE   0
#9   12  TRUE   0
#10  17  TRUE   0
#11  20 FALSE   2
#12  20 FALSE   2
#13  20 FALSE   2
#14  17  TRUE   0
#15  17  TRUE   0
#16  13  TRUE   0
#17  20 FALSE   3
#18  20 FALSE   3
#19  17  TRUE   0
#20  13  TRUE   0

我不知道你是否真的可以避免创建 CRIT 的初步步骤,尽管我建议在创建它时添加 cumsum 然后 运行 一个简单的 cumsum/diff 结束吧。此外,如果您不需要不符合条件的组,最好分配 NA 而不是一些随机数,例如零。这是一个可能的 data.table 总结(另外,您根本不需要 df <- tbl_df(df) 步骤)

library(data.table)
setDT(df)[, CRIT := cumsum(THR < 19)]
df[THR >= 19, GRP := cumsum(c(0L, diff(CRIT)) != 0L) + 1L]
#     THR CRIT GRP
#  1:  13    1  NA
#  2:  17    2  NA
#  3:  19    2   1
#  4:  22    2   1
#  5:  21    2   1
#  6:  19    2   1
#  7:  17    3  NA
#  8:  12    4  NA
#  9:  12    5  NA
# 10:  17    6  NA
# 11:  20    6   2
# 12:  20    6   2
# 13:  20    6   2
# 14:  17    7  NA
# 15:  17    8  NA
# 16:  13    9  NA
# 17:  20    9   3
# 18:  20    9   3
# 19:  17   10  NA
# 20:  13   11  NA