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
我使用飞行运动数据框(约 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