R语言按stage、machine分组生成顺序编号新列的实现方法
问题说明
现有包含stage(阶段号)和machine(机器号)两个字段的数据集,全量数据共38个stage,总数据量超100万行,部分数据示例如下:
stage <- c("Stg1", "Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1","Stg1", "Stg2", "Stg2", "Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg2","Stg10","Stg10","Stg10") machine <- c("132H", "132H","132H", "132H", "132H", "212H", "212H", "212H", "212H", "212H", "217H", "217H", "132H", "132H", "212H", "212H", "212H", "212H", "212H", "217H", "217H", "217H", "132H", "132H", "132H") df <- data.frame(stage,machine)
需求:新增JobStage列,为stage和machine的唯一组合按stage数字从小到大、同stage下machine按顺序的规则分配连续编号,预期输出效果如下:
stage machine JobStage 1 Stg1 132H 1 2 Stg1 132H 1 3 Stg1 132H 1 4 Stg1 132H 1 5 Stg1 132H 1 6 Stg1 212H 2 ... 23 Stg10 132H 7 24 Stg10 132H 7 25 Stg10 132H 7
此前尝试逐行手动赋值效率极低,用dplyr的group_by()+mutate()的代码逻辑错误无法运行:
df %>% group_by(stage, machine) %>% mutate(JobStage = unique(stage) & unique(machine))
解决方案
方法1:dplyr实现(推荐,可读性高,效率适合百万行数据)
核心用dplyr的cur_group_id()函数,该函数会为每个分组分配唯一的连续整数ID,同时需要先处理stage的排序逻辑,避免默认字符排序把Stg10排在Stg2前面:
library(dplyr) df <- df %>% # 提取stage中的数字作为排序依据 mutate(stage_num = as.integer(gsub("Stg", "", stage))) %>% # 按stage数字、machine排序,保证ID顺序符合预期 arrange(stage_num, machine) %>% group_by(stage, machine) %>% # 为每个唯一组合分配ID mutate(JobStage = cur_group_id()) %>% ungroup() %>% # 移除辅助计算的列 select(-stage_num)
如果不需要保留原始数据的行顺序,可以删掉排序逻辑,直接分组后调用cur_group_id()即可,效率会更高。
方法2:base R实现(无需加载第三方包,效率极高)
用interaction()函数生成组合因子,转成整数即可得到唯一ID:
# 提取stage数字做排序 stage_num <- as.integer(gsub("Stg", "", df$stage)) # 按规则排序后生成组合ID df$JobStage <- as.integer(interaction(df$stage[order(stage_num, df$machine)], df$machine[order(stage_num, df$machine)], lex.order = TRUE)) # 若需要保留原始数据的行顺序,执行以下代码 df <- df[order(as.integer(rownames(df))), ]
两种方法处理100万行数据的耗时均在1秒以内,完全满足性能要求。
内容的提问来源于stack exchange,提问作者new2data
相关产品推荐
相关产品推荐

