【问题标题】:Matching across two data frames with certain observations having multiple entries to match against跨两个数据帧进行匹配,某些观察具有多个要匹配的条目
【发布时间】:2015-12-19 05:52:24
【问题描述】:

我使用与以下示例相对应的两个数据框:

# 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))

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

生成的数据框将具有以下品质:

  1. 对于只有一个标识符存在的观察,merge 命令执行all.y = TRUEall.x = FALSE,假设ydta_b
  2. 对于提供多个标识符的观察结果,仅采用dta_a 中的第一个匹配值,而忽略其余值。如果第一个标识符 (A0003) 不匹配,我希望命令尝试匹配下一个标识符 (A0004)。

我参考了merge 命令,但自然而然,dplyr 和其他解决方案都可以。

【问题讨论】:

    标签: r string merge dataframe


    【解决方案1】:

    您可以“融化” 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) 
    

    【讨论】:

    • 是否可以将代码 variable_abc = dta_b$variable_abc[i], variable_df = dta_b$variable_df[i] 更改为一个循环,在该循环中我可以跳过文件中所有可用的变量。我在想一些事情:for (j in length(names(dta_awrd)) -1) { names(dta_awrd)[j] = dta_awrd[,names(dta_awrd)[j]] #Subset for i}。在实际的数据框中,我想要携带更多的列。
    【解决方案2】:

    只是一种方法,但我猜不是最好的方法。刚试了一下。 拆分标识符并根据第一个进行合并。

    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)
    

    如果您没有匹配第一个,您会看到 NA,您可以对它们进行子集化并与第二个合并(“identifier_split.2”)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-13
      • 2017-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-18
      • 1970-01-01
      • 2021-11-14
      相关资源
      最近更新 更多