如何在pivot_wider中按Tijdspunt实现单时间点列的宽表转换?
长表转宽表:按时间点对齐列的解决方案
问题背景
现有长格式R数据框pbmc_total,包含重复的Deelnemernr.(受试者编号),每条记录含donornrs_pbmc、Tijdspunt(时间点)字段,部分受试者存在重复时间点的记录。
原转换代码按行号生成列后缀,导致同时间点的记录被拆成独立列组,不符合需求。期望按Tijdspunt的全局唯一值排序,每个时间点对应一组donornrs_pbmc和Tijdspunt列,无对应时间点的位置填充NA。
输入数据示例
Deelnemernr. donornrs_pbmc Tijdspunt <chr> <chr> <chr> 1 449132 4491321 T1 2 449513 4495131 T1 # 省略重复行
原代码输出(不符合需求)
Deelnemernr. donornrs_pbmc.1 Tijdspunt.1 donornrs_pbmc.2 Tijdspunt.2 <chr> <chr> <chr> <chr> <chr> 1 449132 4491321 T1 4491321 T1 # 省略后续行
期望输出
Deelnemernr. donornrs_pbmc.1 Tijdspunt.1 donornrs_pbmc.2 Tijdspunt.2 donornrs_pbmc.3 Tijdspunt.3 <chr> <chr> <chr> <chr> <chr> <chr> <chr> 1 449132 4491321 T1 4491321 T1 NA NA 3 449423 NA NA NA NA 4494232 T2 # 省略后续行
修改后的代码
# 先获取全局所有唯一的Tijdspunt并排序,分配固定序号 time_points <- pbmc_total %>% distinct(Tijdspunt) %>% arrange(Tijdspunt) %>% mutate(time_id = row_number()) # 关联时间点序号,处理重复记录后转宽表 pbmc_total_wide <- pbmc_total %>% left_join(time_points, by = "Tijdspunt") %>% group_by(Deelnemernr., time_id) %>% # 给同一受试者同一时间点的重复记录加标记 mutate(dup_id = row_number()) %>% unite(col = "time_dup", time_id, dup_id, sep = ".") %>% pivot_longer(cols = c(donornrs_pbmc, Tijdspunt), names_to = "var") %>% mutate(var_name = paste0(var, ".", time_dup)) %>% select(Deelnemernr., var_name, value) %>% pivot_wider(names_from = var_name, values_from = value)
代码逻辑说明
- 全局时间点映射:先提取所有唯一时间点并排序,给每个时间点分配固定的
time_id,确保所有受试者的同一时间点对应相同的列后缀前缀。 - 重复记录标记:对同一受试者同一时间点的多条记录添加
dup_id,区分同一时间点下的不同记录。 - 列名生成:合并
time_id和dup_id生成唯一标识,再与原字段名拼接,得到带时间点+重复标记的列名。 - 转宽表:通过两次
pivot转换,最终生成按时间点对齐的宽表结构。
如果同一受试者同一时间点的重复记录仅需保留一条,可使用简化版代码:
# 简化版:同一受试者同一时间点只保留第一条记录 time_points <- pbmc_total %>% distinct(Tijdspunt) %>% arrange(Tijdspunt) %>% mutate(time_id = row_number()) pbmc_total_wide <- pbmc_total %>% left_join(time_points, by = "Tijdspunt") %>% pivot_longer(cols = c(donornrs_pbmc, Tijdspunt), names_to = "var") %>% mutate(var_name = paste0(var, ".", time_id)) %>% select(Deelnemernr., var_name, value) %>% pivot_wider(names_from = var_name, values_from = value, values_fn = first)
内容的提问来源于stack exchange,提问作者Debbie Oomen
相关产品推荐
相关产品推荐

