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

R语言如何按指定条件匹配两个数据框的最优对应行

R语言双数据框条件匹配实现方案

完全可以通过fuzzyjoin包结合马氏距离计算实现你的需求,针对你的数据规模(仅数千行),以下两种方案均可高效运行:

前置准备

首先统一列名格式,计算马氏距离所需的协方差矩阵:

# 安装所需依赖包
install.packages("dplyr")
# 如使用方案1需额外安装fuzzyjoin
install.packages("fuzzyjoin")

# 加载包
library(dplyr)

# 替换列名中的空格为下划线,避免语法报错
colnames(df1) <- gsub(" ", "_", colnames(df1))
colnames(df2) <- gsub(" ", "_", colnames(df2))

# 提取四个数值指标列名
criteria_cols <- paste0("criteria_", 1:4)
# 基于df2的数值列计算协方差矩阵,用于马氏距离计算
cov_matrix <- cov(df2[, criteria_cols])

方案1:基于fuzzyjoin包实现

逻辑更直观,符合你最初的工具选型预期:

library(fuzzyjoin)

result <- df1 %>%
  # 先按type_1、type_2完全匹配,筛选所有符合基础条件的配对
  fuzzy_left_join(
    df2,
    by = c("type_1", "type_2"),
    match_fun = list(`==`, `==`)
  ) %>%
  # 逐行计算配对的马氏距离
  rowwise() %>%
  mutate(
    mahalanobis_dist = mahalanobis(
      x = c_across(all_of(paste0(criteria_cols, ".x"))),
      center = c_across(all_of(paste0(criteria_cols, ".y"))),
      cov = cov_matrix
    )
  ) %>%
  ungroup() %>%
  # 按df1的每条记录分组,取距离最小的最优匹配
  group_by(id.x) %>%
  slice_min(mahalanobis_dist, n = 1, with_ties = FALSE) %>%
  ungroup()

# 可选:重命名列区分来源
colnames(result) <- gsub("\\.x", "_df1", colnames(result))
colnames(result) <- gsub("\\.y", "_df2", colnames(result))

方案2:轻量分组匹配实现(无需fuzzyjoin)

运行效率更高,适合后续数据规模扩展的场景:

# 按type_1、type_2拆分两个数据框为分组列表
df1_groups <- df1 %>% group_by(type_1, type_2) %>% group_split()
df2_groups <- df2 %>% group_by(type_1, type_2) %>% group_split()

# 定义分组内匹配函数
group_match <- function(df1_g) {
  # 匹配df2中对应type的分组
  target_idx <- which(sapply(df2_groups, function(x) {
    x$type_1[1] == df1_g$type_1[1] && x$type_2[1] == df1_g$type_2[1]
  }))
  if(length(target_idx) == 0) return(NULL)
  df2_g <- df2_groups[[target_idx]]
  
  # 计算当前分组所有配对的马氏距离
  dist_matrix <- apply(df1_g[, criteria_cols], 1, function(x) {
    apply(df2_g[, criteria_cols], 1, function(y) mahalanobis(x, y, cov_matrix))
  })
  # 取每个df1行的最小距离对应df2行
  min_pos <- apply(dist_matrix, 2, which.min)
  
  # 合并匹配结果
  cbind(
    df1_g %>% rename_with(~paste0(., "_df1")),
    df2_g[min_pos, ] %>% rename_with(~paste0(., "_df2")),
    mahalanobis_dist = dist_matrix[cbind(min_pos, 1:ncol(dist_matrix))]
  )
}

# 遍历所有分组得到最终结果
final_result <- bind_rows(lapply(df1_groups, group_match))

可选替换

如果不需要使用马氏距离,可将上述代码中的距离计算逻辑替换为欧氏距离:sqrt(sum((x - y)^2)),或其他你需要的距离计算规则。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:27:02