You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于另一数据框为数据框中人员匹配相同ID(无匹配填NA)

问题:匹配两个数据框的人员ID,无匹配则填充NA

我有两个数据集df和df2,是大型杂乱数据框的简化版本。在df中,我已按belt(腰带)和weight(体重)分组,为每个人创建了唯一id。现在需要将df中对应人员的id匹配到df2中,匹配条件是姓名相同且属于同一belt和weight分组。df2中存在不在df里的人员,这类人员的id需填充为NA。需注意:同一人在不同体重级别参赛时id不同,必须严格按belt和weight分组匹配。

原始数据集df

belt     weight rank id        name
1  purple open class    1 55  Tom Cruise
2   black    rooster    2 79 Emma Watson
3    blue    feather    3 63    John Doe
4    blue    feather    4 63    John Doe
5  purple open class    5 55  Tom Cruise
6   brown      heavy    6  3  James Bond
7  purple open class    7 55  Tom Cruise
8  purple      heavy    8 61  Tom Cruise
9   black open class    9 70    Jane Doe
10 purple      heavy   10 61  Tom Cruise

待匹配数据集df2

belt2    weight2 rank2        name points
1  purple open class     1  Tom Cruise    100
2   black    rooster     2 Emma Watson     30
3    blue    feather     3    John Doe     50
4    blue    feather     4    John Doe     50
5  purple open class     5  Tom Cruise    100
6   brown      heavy     6  James Bond    200
7   black    rooster     7    Jon Snow     92
8  purple      heavy     8  Tom Cruise     77
9   black open class     9    Jane Doe     88
10 purple      heavy    10  Tom Cruise     77

期望结果

belt2    weight2 rank2 id           name points
1  purple open class     1 55     Tom Cruise    100
2   black    rooster     2 79    Emma Watson     30
3    blue    feather     3 63       John Doe     50
4    blue    feather     4 63       John Doe     50
5  purple open class     5 55     Tom Cruise    100
6   brown      heavy     6  3     James Bond    200
7   black    rooster     7 NA       Jon Snow     92
8  purple      heavy     8 61     Tom Cruise     77
9   black open class     9 70       Jane Doe     88
10 purple      heavy    10 61     Tom Cruise     77

数据集构建代码

# df
belt <- c("purple", "black", "blue", "blue", "purple", "brown", "purple", "purple", "black", "purple")
weight <- c("open class", "rooster", "feather", "feather", "open class", "heavy", "open class", "heavy", "open class", "heavy")
rank <- 1:10
id <- c(55, 79, 63, 63, 55, 3, 55, 61, 70, 61)
names <- c("Tom Cruise", "Emma Watson", "John Doe", "John Doe", "Tom Cruise", "James Bond", "Tom Cruise", "Tom Cruise", "Jane Doe", "Tom Cruise")
(df <- data.frame(belt, weight, rank, id, name = names))

#df2
belt2 <- c("purple", "black", "blue", "blue", "purple", "brown", "black", "purple", "black", "purple")
weight2 <- c("open class", "rooster", "feather", "feather", "open class", "heavy", "rooster", "heavy", "open class", "heavy")
rank2 <- 1:10
names2 <- c("Tom Cruise", "Emma Watson", "John Doe", "John Doe", "Tom Cruise", "James Bond", "Jon Snow", "Tom Cruise", "Jane Doe", "Tom Cruise")
points <- c(100, 30, 50, 50, 100, 200, 92, 77, 88, 77)
(df2 <- data.frame(belt2, weight2, rank2, name = names2, points))

解决方案

方法1:Base R实现

通过创建唯一映射表,再进行左连接匹配:

# 提取df中唯一的(belt, weight, name)与id的映射关系
id_map <- unique(df[, c("belt", "weight", "name", "id")])

# 对齐df2的列名,方便合并
colnames(df2)[1:2] <- c("belt", "weight")

# 左连接匹配id,保留df2所有行,无匹配则id为NA
result <- merge(df2, id_map, by = c("belt", "weight", "name"), all.x = TRUE)

# 恢复df2原列名
colnames(result)[1:2] <- c("belt2", "weight2")

# 调整列顺序与期望结果一致
result <- result[, c("belt2", "weight2", "rank2", "id", "name", "points")]

print(result)

方法2:dplyr包实现(更简洁)

使用dplyr的管道语法完成匹配:

library(dplyr)

result_df2 <- df2 %>%
  # 重命名列以匹配df的列名
  rename(belt = belt2, weight = weight2) %>%
  # 左连接df的唯一映射表,匹配三列
  left_join(unique(df[, c("belt", "weight", "name", "id")]), 
            by = c("belt", "weight", "name")) %>%
  # 恢复原列名
  rename(belt2 = belt, weight2 = weight) %>%
  # 调整列顺序
  select(belt2, weight2, rank2, id, name, points)

print(result_df2)

两种方法均可得到符合要求的结果,df2中不存在于df的人员id会自动填充为NA。

内容的提问来源于stack exchange,提问作者bandcar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:25:26