如何基于Codes匹配Code1或Code2合并两个data.frame?
问题描述
我有一个数据框df1:
| Codes | Oxy | Date |
|---|---|---|
| 100095 | 30% | 1 |
| 100096 | 50% | 1 |
| 100097 | 20% | 1 |
| 100095 | 40% | 2 |
| 100096 | 10% | 2 |
| 100097 | 20% | 2 |
另有数据框df2,需要将其与df1合并:
| Code1 | Code2 | Spp |
|---|---|---|
| 100095 | 345550 | Sz |
| 104568 | 100096 | Cg |
| 983488 | 100097 | As |
需求是:当df1$Codes等于df2$Code1或df2$Code2时,将df2对应行的Spp合并到df1中。
尝试过以下代码,但未实现预期效果:
df3 <- merge(x = df1, y = df2, all.x = TRUE)
该代码没有按代码匹配,只是把df2的所有数据复制到df1的每一行,需要正确匹配后添加Spp变量。
解决方案
核心思路是先将df2转换为长格式,让每个代码(无论来自Code1还是Code2)都对应唯一的Spp,再与df1按代码匹配合并。
Base R 实现
# 将df2转为长格式,提取所有代码与对应Spp df2_long <- reshape(df2, varying = c("Code1", "Code2"), v.names = "Code", direction = "long", idvar = "Spp", times = c("Code1", "Code2")) df2_long <- df2_long[, c("Code", "Spp")] # 按Codes与Code匹配合并 df3 <- merge(df1, df2_long, by.x = "Codes", by.y = "Code", all.x = TRUE)
tidyverse 实现(dplyr + tidyr)
如果习惯使用tidyverse工具链,代码更直观:
library(dplyr) library(tidyr) # 转换df2为长格式 df2_long <- df2 %>% pivot_longer(cols = c(Code1, Code2), names_to = "Code_Type", values_to = "Code") %>% select(Code, Spp) # 左连接df1和转换后的df2 df3 <- df1 %>% left_join(df2_long, by = c("Codes" = "Code"))
最终结果
两种方法得到的df3如下:
| Codes | Oxy | Date | Spp |
|---|---|---|---|
| 100095 | 30% | 1 | Sz |
| 100095 | 40% | 2 | Sz |
| 100096 | 50% | 1 | Cg |
| 100096 | 10% | 2 | Cg |
| 100097 | 20% | 1 | As |
| 100097 | 20% | 2 | As |
内容的提问来源于stack exchange,提问作者Eduardo Segura
相关产品推荐
相关产品推荐

