如何用dplyr合并含不同时间观测的两个R数据框?
解决方案(基于dplyr/tidyr)
首先加载所需工具包:
library(tidyverse)
先定义原始数据(与你提供的内容一致):
row11 <- c("a", "c", "2000", "2001", "2005") row12 <- c("", "", 7, 10, 15) f1 <- as.data.frame(rbind(row11, row12)) row21 <- c("a", "b", "c", "2002", "2005") row22 <- c("", "", "", 1, 15) f2 <- as.data.frame(rbind(row21, row22))
单个数据框的处理函数
编写通用函数统一处理f1和f2,将其转换为目标格式的单行数据:
process_df <- function(df) { # 提取第一行作为列名,第二行作为有效数据行 colnames(df) <- df[1, ] df_data <- df[-1, ] %>% mutate(across(everything(), as.character)) # 分离分类列(a、b、c)与年份列 cat_cols <- c("a", "b", "c") year_cols <- setdiff(colnames(df_data), cat_cols) # 转换为长格式,统一处理年份和对应数值 df_long <- df_data %>% pivot_longer(cols = all_of(year_cols), names_to = "year", values_to = "value") %>% mutate(year = as.integer(year), value = ifelse(value == "", NA, as.numeric(value))) # 补全2000-2005所有年份,再转回宽格式,同时补全缺失的分类列 df_wide <- df_long %>% complete(year = 2000:2005) %>% pivot_wider(names_from = year, values_from = value) %>% mutate(across(all_of(cat_cols), ~ ifelse(is.na(.), "", .))) return(df_wide) }
合并处理结果
分别处理两个数据框后,合并得到最终的f3:
f1_processed <- process_df(f1) f2_processed <- process_df(f2) f3 <- bind_rows(f1_processed, f2_processed) # 调整列顺序:先分类列a、b、c,再按年份顺序排列2000-2005 f3 <- f3 %>% select(all_of(c("a", "b", "c")), as.character(2000:2005))
查看最终结果:
print(f3) # 输出与预期一致: # a b c 2000 2001 2002 2003 2004 2005 # 1 "" "" "" 7 10 NA NA NA 15 # 2 "" "" "" NA NA 1 NA NA 15
说明
- 通用函数
process_df避免重复代码,统一处理逻辑 - 用
complete补全所有目标年份,缺失值自动填充NA - 通过
pivot_longer和pivot_wider完成长/宽格式转换,是tidyverse处理此类结构调整的标准流程
内容的提问来源于stack exchange,提问作者MPB_2022
相关产品推荐
相关产品推荐

