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

如何比较行数不同的两个tibble多观测并实现自定义匹配

Alright, let's work through your problem with the tools you're using (dplyr 0.7.4 + R 3.4.1). The goal is to match each value of b in tibble A to any c in tibble C using a custom comparison function, then pull the first matching d value (or NA if no match exists). Here are a few solid approaches, starting with dplyr-focused solutions:

1. dplyr + purrr (Row-wise Processing)

This is the most straightforward dplyr-compatible method for your version. We'll use rowwise() to handle each row of A individually, then use simple logic to check matches in C.

First, let's set up example data and a custom comparison function (you can swap this out for your own logic):

library(dplyr)
library(purrr)

# Example tibbles
set.seed(123)
tibble_A <- tibble(b = c("apple", "banana", "cherry", "date", "elderberry"))
tibble_C <- tibble(c = c("app", "ban", "cher", "dat", "berry"), d = c("fruit1", "fruit2", "fruit3", "fruit4", "fruit5"))

# Custom comparison function: Check if b starts with c (works in R 3.4.1)
custom_match <- function(x, y) {
  substr(x, 1, nchar(y)) == y
}

Now apply the logic:

matched_result <- tibble_A %>%
  rowwise() %>%
  mutate(d = {
    # Find all d values in C where the custom match is true
    matching_ds <- tibble_C$d[custom_match(b, tibble_C$c)]
    # Return first match if exists, else NA
    if (length(matching_ds) > 0) matching_ds[1] else NA_character_
  }) %>%
  ungroup()

# View the result
print(matched_result)

2. Cartesian Product + Filter + Grouped Selection

If you prefer avoiding rowwise() (which can be slower for large datasets), you can generate all possible combinations of A and C, filter for matches, then keep only the first match per row in A. Note that dplyr 0.7.4 doesn't have cross_join(), so we'll use expand.grid() for compatibility:

matched_result_2 <- tibble_A %>%
  # Add a row ID to track original rows in A
  mutate(row_id = row_number()) %>%
  # Generate all combinations of A and C
  expand.grid(b = .$b, c = tibble_C$c, d = tibble_C$d, row_id = .$row_id) %>%
  as_tibble() %>%
  # Filter rows where custom match is true
  filter(custom_match(b, c)) %>%
  # Keep only the first match per original row in A
  group_by(row_id) %>%
  slice(1) %>%
  ungroup() %>%
  # Join back to original A to include rows with no matches (NA for d)
  right_join(tibble_A %>% mutate(row_id = row_number()), by = c("row_id", "b")) %>%
  # Clean up columns
  select(b, d)

print(matched_result_2)

3. Alternative: data.table (For Larger Datasets)

If you're working with big data and need faster performance, data.table is a great alternative. It handles row-wise operations efficiently:

library(data.table)

# Convert tibbles to data.tables
setDT(tibble_A)
setDT(tibble_C)

# Apply matching logic
matched_result_dt <- tibble_A[, d := {
  matching_ds <- tibble_C$d[custom_match(b, tibble_C$c)]
  if (length(matching_ds) > 0) matching_ds[1] else NA_character_
}, by = b]

print(matched_result_dt)

Custom Function Flexibility

The custom_match() function can be adapted to any logic you need. For example, if you're working with numerical values and want to match within a range:

# Numerical example
tibble_A_num <- tibble(b = c(1.2, 3.5, 5.7, 8.1))
tibble_C_num <- tibble(c = c(1, 3, 6, 8), d = c("low", "mid", "high", "very_high"))

# Custom function: Match if b is within ±0.5 of c
num_match <- function(x, y) {
  abs(x - y) <= 0.5
}

# Apply with the first dplyr method
num_result <- tibble_A_num %>%
  rowwise() %>%
  mutate(d = {
    matches <- tibble_C_num$d[num_match(b, tibble_C_num$c)]
    if (length(matches) > 0) matches[1] else NA_character_
  }) %>%
  ungroup()

print(num_result)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:21:39