R语言:按条件合并数据框行角色值的问题及解决需求
解决DataFrame合并同一联系人角色的问题
嘿,我来帮你搞定这个DataFrame合并的问题!首先咱们先确认下你提供的示例数据结构:
df<-structure(list(First = c("John", "John", "John", "Teddy", "Teddy", "Jess", "Jess", "Jess"), Last = c("Smith", "Smith", "Smith", "Bush", "Bush", "Clinton", "Clinton", "Clinton"), C_ID = c(10045L, 10045L, 10045L, 10046L, 10046L, 10050L, 10050L, 10050L), OrgName = c("Acme", "Acme", "Acme", "Acme", "Acme", "Consult", "Consult", "Consult" ), O_ID = c(901L, 901L, 901L, 901L, 901L, 904L, 904L, 904L), Program = c("Buildings", "Buildings", "Homes", "Buildings", "Buildings", "Homes", "Homes", "Homes"), Role = c("Primary", "Communications", "Primary", "Primary", "Signatory", "Signatory", "Primary", "Communications")), .Names = c("First", "Last", "C_ID", "OrgName", "O_ID", "Program", "Role"), class = "data.frame", row.names = c(NA, -8L))
你之前用ddply遇到的两个问题,根源其实很明确:
- 分组时用了
df$C_ID这种写法,导致分组后的列名混乱、顺序被打乱; - 直接对整个分组应用
paste,会把所有列的内容强行合并,哪怕是值完全相同的列(比如姓名)也会变成c("John", "John")这种奇怪格式。
下面给你两种靠谱的解决方法,分别适配不同的工具偏好:
方法一:用dplyr(推荐,高效又简洁)
dplyr是现在处理DataFrame的主流工具,语法直观,处理10万行的数据集也毫无压力:
library(dplyr) df_cleaned <- df %>% # 按联系人ID、项目、机构ID进行分组 group_by(C_ID, Program, O_ID) %>% # 对非Role列保留唯一值(同一分组下这些值本来就相同),合并Role列 summarize( # 用across批量处理所有非Role列,取第一个值(和unique效果一致) across(-Role, ~first(.)), # 合并去重后的角色,用逗号分隔成字符串 Role = paste(unique(Role), collapse = ", ") ) %>% # 取消分组(后续操作更灵活) ungroup()
如果你的数据集有很多非Role列,across(-Role, ~first(.))这一行就能批量处理所有列,不用手动列每个字段名,非常省心。
方法二:用plyr(适配你原来的工具链)
如果你习惯用plyr,只需要自定义一个分组处理函数,针对性合并Role列即可:
library(plyr) df_cleaned_plyr <- ddply(df, .(C_ID, Program, O_ID), function(group_data) { data.frame( First = unique(group_data$First), Last = unique(group_data$Last), OrgName = unique(group_data$OrgName), Role = paste(unique(group_data$Role), collapse = ", ") ) })
这里的核心是不再直接把paste传给ddply,而是写一个匿名函数:对每个分组,相同值的列用unique()保留单个值,Role列则合并成逗号分隔的字符串。
最终效果
处理后的结果会完全符合你的需求:
- John(C_ID=10045)在Buildings项目下的Role变为
"Primary, Communications" - John在Homes项目下的Role是
"Primary" - Teddy的Buildings项目Role是
"Primary, Signatory" - Jess的Homes项目Role是
"Signatory, Primary, Communications"
所有其他列(姓名、机构名等)都保留了单个正确的值,列名和顺序也和原数据集完全一致,不会再出现混乱的情况。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

