匹配两个数据帧,其中某些观察结果具有多个匹配的条目

时间:2015-09-22 09:47:56

标签: r string merge dataframe

我处理了与以下示例相对应的两个数据框:

# Data sets
set.seed(1)
dta_a <- data.frame(some_value = runif(n = 10), 
                    identifier=c("A0001","A0002","A0003","A0004","A0005",
                                 "A0006","B0001","B0002","B0003","B0004"),
                    other_val = runif(n = 10))
dta_b <- data.frame(variable_abc = runif(n = 6), 
                    identifier=c("A0001","A0002","A0003,A0004,A0005,C0001",
                                 "B0001,B0002","B0003","B0004"),
                    variable_df = runif(n = 6))

我想合并这两个数据帧并获得类似于下面所示的数据框:

Desired results: data frame

结果数据框具有以下特性:

  1. 对于仅存在一个标识符的观察,merge命令与all.y = TRUEall.x = FALSE一起执行,假设y为{{1} }}。
  2. 对于提供多个标识符的观察结果,只会从dta_b获取第一个匹配的值,并忽略其余值。如果第一个标识符(dta_a)上没有匹配项,我希望命令尝试匹配下一个标识符(A0003)。
  3. 我引用了A0004命令,但自然地,merge和其他解决方案都没问题。

2 个答案:

答案 0 :(得分:3)

你可以'融化'dta_b,以便每个标识符有一行带有首选项顺序,然后加入所有标识符:

library(dplyr)
library(tidyr)
melt_dta_b = lapply(1:nrow(dta_b), function(i){
 split_identifier = strsplit(as.character(dta_b$identifier[i]), split = ",", fixed = TRUE)[[1]]
 data_frame(identifier = split_identifier, 
         original_identifier = dta_b$identifier[i], original_row = i, preference = 1:length(identifier), 
         variable_abc = dta_b$variable_abc[i], variable_df = dta_b$variable_df[i])
})
melt_dta_b = rbind_all(melt_dta_b)

此时,您只能选择具有最高优先级分数的那个:

joined_df = left_join(melt_dta_b, dta_a) %>% 
  filter(!is.na(some_value)) %>% 
  group_by(original_row) %>% 
  filter(preference == min(preference)) %>% 
  ungroup()

更新

为了不按名称显式调用变量,您可以使用以下代码绑定原始df的所有“未使用”列:

melt_dta_b = lapply(1:nrow(dta_b), function(i){
  tmp = dta_b[i,]
  split_identifier = strsplit(as.character(tmp$identifier), split = ",", fixed = TRUE)[[1]]
  colnames(tmp)[2] = "original_identifier"
  data_frame(identifier = split_identifier, original_row = i, preference = 1:length(identifier)) %>% 
    cbind(tmp)
})
melt_dta_b = rbind_all(melt_dta_b) 

答案 1 :(得分:1)

只是这样做的一种方式,但不是我想的最佳方式。刚试了一下。 拆分标识符并根据第一个进行合并。

dta_a$identifier = as.vector(dta_a$identifier)
dta_a1 = data.frame(dta_a, identifier_split = do.call(rbind, strsplit(dta_a$identifier, split = ",", fixed = T)))
dta_b$identifier = as.vector(dta_b$identifier)
dta_b1 = data.frame(dta_b, identifier_split = do.call(rbind, strsplit(dta_b$identifier, split = ",", fixed = T)))

dta_join = merge(dta_a1, dta_b1, by =  "identifier_split.1", all.x = F, all.y = T)

如果你没有匹配第一个,你会看到NAs,你可以将它们分组并与第二个合并(&#34; identifier_split.2&#34;)