在R语言中重塑含多列的重复ID数据集
R语言多列数据集重塑解决方案
嘿,我来帮你搞定这个R里的数据重塑问题!先结合你描述的数据集结构,我先模拟一个贴近你场景的示例数据,然后给出几种常见重塑需求的解决方案,你可以根据自己的实际目标调整。
先模拟你的数据集结构
首先用代码生成一个和你描述匹配的样例数据,方便你对照测试:
set.seed(123) # 保证结果可复现 df <- data.frame( Id = rep(c("A", "B", "C"), each = 3), # 每个Id重复3次(对应3年) Start_Year = rep(c(2020, 2019, 2021), each = 3), # 每个Id的起始年份重复 Year = c(2020, 2021, 2022, 2019, 2020, 2021, 2021, 2022, 2023), # 每条记录的年份 Location = sample(c("Loc1", "Loc2"), 9, replace = TRUE), # 仅两种地点取值 Sub_Location = c("SubA", "SubA", NA, "SubB", NA, NA, "SubC", "SubC", "SubC") # 子地点可能为NULL )
常见重塑场景的代码方案
1. 长格式转宽格式(每个Id一行,年份作为列)
如果想把每个Id的多年数据合并成一行,用tidyr::pivot_wider()是最方便的:
library(tidyr) library(dplyr) wide_df <- df %>% pivot_wider( id_cols = c(Id, Start_Year), # 保留每个Id固定不变的列 names_from = Year, # 用年份作为新列名的前缀 values_from = c(Location, Sub_Location), # 需要展开的列 names_sep = "_" # 列名分隔符,比如生成`Location_2020`这样的列 )
2. 处理子地点的NULL值
如果想把每个Id的Sub_Location缺失值填充(比如用该Id最近的非空值),或者统一为该Id的第一个/最后一个非空子地点:
# 方案1:上下填充缺失的子地点值 filled_sub_loc_df <- df %>% group_by(Id) %>% fill(Sub_Location, .direction = "downup") %>% # 先向下填充,再向上填充覆盖所有缺失 ungroup() # 方案2:统一用每个Id的第一个非空子地点值 fixed_sub_loc_df <- df %>% group_by(Id) %>% mutate(Sub_Location = first(na.omit(Sub_Location))) %>% # 提取第一个非空值替换所有 ungroup()
3. 按地点分组聚合数据
如果需要按Location统计年度数据(比如每个地点每年的唯一Id数量):
aggregated_df <- df %>% group_by(Location, Year) %>% summarise( Unique_Id_Count = n_distinct(Id), Avg_Start_Year = mean(Start_Year), .groups = "drop" # 取消分组,返回普通数据框 )
4. 宽格式转长格式(如果你的原始数据是宽格式,需要转成你描述的长格式)
如果你的数据原本是宽格式(比如每个Id一行,年份列是分散的),可以用pivot_longer()转成长格式:
# 先模拟一个宽格式示例 wide_example <- data.frame( Id = c("A", "B"), Start_Year = c(2020, 2019), Location_2020 = "Loc1", Location_2021 = "Loc2", Sub_Location_2020 = "SubA", Sub_Location_2021 = NA ) # 转成长格式 long_df <- wide_example %>% pivot_longer( cols = matches("(Location|Sub_Location)_\\d{4}"), # 匹配带年份的列 names_to = c(".value", "Year"), # .value保留原列名前缀,Year提取年份 names_pattern = "(.*)_(\\d{4})" # 用正则拆分列名的前缀和年份 ) %>% mutate(Year = as.integer(Year)) # 把年份转成整数类型
如果你的重塑需求更具体(比如要输出特定结构的数据集),可以补充细节后再调整方案哦~
内容的提问来源于stack exchange,提问作者alants




