R语言如何按code分组转name多列 避免left_join产生重复行
R实现长表转宽表:按分组将同一列值拆分为多列
问题说明
现有存储code与对应name字段的dataframe,code为业务唯一标识,但单个code可能对应多个name值。为避免后续执行left_join()操作时产生重复行,需要重构表结构:按code分组,将关联的多个name值拆分为name1/name2/...格式的独立列存储,无匹配值的位置可填充NA、空字符串等自定义值。
输入样例
df <- data.frame( code = c(1,1,2), name = c("a", "b", "c") )
期望输出样例
resdf <- data.frame( code = c(1,2), name1 = c("a", "c"), name2 = c("b", "") )
可行实现方案
方案1:tidyverse 实现(日常分析推荐,代码简洁易读)
核心逻辑是先按code分组,给每个分组内的name按顺序生成列名序号,再通过宽表转换函数完成结构重组,缺失值可自定义填充规则:
library(dplyr) library(tidyr) resdf <- df %>% group_by(code) %>% # 为分组内每个name生成name1/name2...的列标识 mutate(col_id = paste0("name", row_number())) %>% ungroup() %>% # 长转宽,values_fill参数控制缺失值填充内容,填NA就写values_fill = NA pivot_wider( names_from = col_id, values_from = name, values_fill = "" )
运行结果与期望输出完全一致,即使单个code对应更多name值(比如3个、4个),代码也会自动生成对应数量的name列,不需要手动提前指定列数。
方案2:基础R实现(无需安装第三方包)
如果不想加载第三方依赖,用基础R的reshape函数搭配分组序号生成即可实现:
# 按code分组,为每个name生成对应的列序号 df$col_id <- paste0("name", with(df, ave(code, code, FUN = seq_along))) # 执行长表转宽表操作 resdf <- reshape( df, idvar = "code", timevar = "col_id", direction = "wide" ) # 清理自动生成的列名前缀 colnames(resdf) <- gsub("name\\.", "", colnames(resdf)) # 可选:将NA替换为空字符串,不需要可注释掉该行 resdf[is.na(resdf)] <- ""
内容的提问来源于stack exchange,提问作者Gmichael
相关产品推荐
相关产品推荐

