处理需保留重复项的pivot_wider数据透视问题
多行转单行数据的解决方案
中文版本的示例数据代码
# 构造示例数据集 dat1 <- data.frame( 参与者 = c("Peter", "Peter", "Peter", "Peter", "Peter", "Peter", "Carol", "Carol", "Carol", "Carol", "Carol", "Carol"), 组ID = c(1, 1, 2, 2, 3, 3, 3, 3, 4, 5, 5, 5), 联系方式类型 = c("邮箱", "邮箱", "邮箱", "电话", "办公电话", "家庭电话", "家庭电话", "家庭电话", "其他", "网址", "传真", "办公传真"), 联系方式内容 = c("mail@gmail.com", "anothermail@gmail.com", "thirdmail@gmail.com", 1234567890, 0987654321, 587290164389, 36237862873, 34384738923, 43432894274, "website.com", 32489789432, 23467832648937) )
一、之前的错误纠正
你之前的代码出错,是因为没把GroupID当成分组依据——同名参与者如果属于不同GroupID,那是完全不同的记录,必须用「参与者+组ID」作为唯一标识来分组,不然会把不同组的同名数据误合并到一起。
二、自动重命名重复标签的R代码
先给同一「参与者+组ID」下重复的联系方式类型加个序号后缀,这样用pivot_wider就不会因为列名重复报错了:
library(dplyr) library(tidyr) # 处理重复标签:给同一参与者-组内的重复联系方式类型加序号 dat_processed <- dat1 %>% # 按参与者、组ID、联系方式类型分组,给同类型的条目编序号 group_by(参与者, 组ID, 联系方式类型) %>% mutate(type_seq = row_number()) %>% ungroup() %>% # 重复的类型名加序号(比如邮箱_1、邮箱_2),唯一类型保持原名 mutate(联系方式类型 = ifelse(type_seq > 1, paste0(联系方式类型, "_", type_seq), 联系方式类型)) %>% select(-type_seq) # 删掉临时用的序号列
三、合并多行数据为单行的代码(搞定2000条问题数据)
用处理好的标签,直接合并成单行,顺便完成2000条数据的清理:
# 把多行数据合并成单行 dat_wide <- dat_processed %>% pivot_wider( id_cols = c(参与者, 组ID), # 用来标识唯一记录的列 names_from = 联系方式类型, # 把联系方式类型转成列名 values_from = 联系方式内容, # 把联系方式内容填到对应列里 values_fill = NA # 空值用NA填充 ) # 查看合并后的结果 print(dat_wide)
运行后,同一「参与者+组ID」的所有联系方式都会合并到一行里,重复的类型(比如Peter的两个邮箱)会变成邮箱、邮箱_2这样的列名,不会再冲突。
四、更省事的写法
不用单独处理标签,直接在pivot_wider里一步搞定重命名和合并:
dat_wide_simple <- dat1 %>% group_by(参与者, 组ID, 联系方式类型) %>% mutate(type_seq = row_number()) %>% ungroup() %>% pivot_wider( id_cols = c(参与者, 组ID), names_from = c(联系方式类型, type_seq), names_glue = "{联系方式类型}{ifelse(type_seq > 1, paste0('_', type_seq), '')}", values_from = 联系方式内容, values_fill = NA )
逻辑和分步处理一样,只是把标签重命名的步骤整合到了pivot过程里,代码更紧凑。
内容的提问来源于stack exchange,提问作者user22757672
相关产品推荐
相关产品推荐

