以编程方式查找并修正行列长度不同的DataFrame中的ID
处理行列长度不同且存在ID变更的面板DataFrame方案
我来给你梳理下处理这类问题的具体步骤,结合你给出的示例代码,咱们一步步来解决:
首先先把你给出的DF1代码整理好,同时我补全一个DF2的示例(模拟部分站点ID变更的情况),方便后续演示:
# 你的DF1示例代码 Year <- c(2006,2006,2006,2006) Name <- as.character(c("A","B","C","D.B")) Qtr.2 <- as.numeric(c(14,32,62,40)) Code <- as.character(c(123,456,789,101)) DF1 <- data.frame(Year, Name, Qtr.2, Code, stringsAsFactors = FALSE) # 模拟DF2(部分站点Code变更:B的Code从456变457,D.B的Code从101变102) Year2 <- c(2007,2007,2007,2007) Name2 <- as.character(c("A","B","C","D.B")) Qtr.3 <- as.numeric(c(16,35,60,42)) Code2 <- as.character(c(123,457,789,102)) DF2 <- data.frame(Year = Year2, Name = Name2, Qtr.3 = Qtr.3, Code = Code2, stringsAsFactors = FALSE)
1. 先搞定ID变更的映射关系
站点的Name一般是稳定的(不会随便改名),所以咱们用它当桥梁,把新旧ID(Code)对应起来。如果有官方的ID变更对照表直接用最好,没有的话就用Name匹配生成映射:
library(dplyr) # 合并两个DF的Name和Code,生成映射表 id_mapping <- unique(rbind( DF1[, c("Name", "Code")] %>% rename(Old_Code = Code), DF2[, c("Name", "Code")] %>% rename(New_Code = Code) )) %>% group_by(Name) %>% fill(Old_Code, New_Code, .direction = "downup") # 填充每个Name对应的新旧Code # 查看映射表 print(id_mapping)
2. 统一两个DataFrame的ID编码
接下来把两个DF的ID统一成同一套(比如都用新ID),这样后续合并就有了一致的匹配键:
# 给DF1添加统一ID(用新Code) DF1 <- DF1 %>% left_join(id_mapping[, c("Name", "New_Code")], by = "Name") %>% rename(Unified_Code = New_Code) # 给DF2直接把Code重命名为统一ID DF2 <- DF2 %>% rename(Unified_Code = Code)
3. 合并处理行列长度不同的面板数据
因为两个DF行列长度不同,说明有的站点在某一年有数据、另一年没有,或者部分年份数据缺失。咱们用**全连接(full_join)**保留所有观测,缺失值用NA填充,之后再按需处理:
# 按年份和统一ID合并两个DF merged_df <- full_join( DF1[, c("Year", "Unified_Code", "Name", "Qtr.2")], DF2[, c("Year", "Unified_Code", "Name", "Qtr.3")], by = c("Year", "Unified_Code", "Name") ) # 查看合并结果 print(merged_df)
可选:转换成平衡面板数据
如果需要把数据整理成标准的平衡面板(每个站点每年都有一行),可以用tidyr的complete()函数补全缺失的年份和站点组合:
library(tidyr) balanced_panel <- merged_df %>% complete(Year, Unified_Code, fill = list(Qtr.2 = NA, Qtr.3 = NA)) %>% left_join(id_mapping[, c("Unified_Code", "Name")], by = "Unified_Code") # 补回站点名称 print(balanced_panel)
内容的提问来源于stack exchange,提问作者Peter_Evan
相关产品推荐
相关产品推荐

