【问题标题】:Loop Through 2 Dataframes to Identify Similar Columns for Joins循环遍历 2 个数据框以识别相似的连接列
【发布时间】:2019-01-15 14:39:30
【问题描述】:

我在这里有 2 个可重现的数据框。我试图确定哪一列包含与另一列相似的值。我希望我的代码会从每列中随机选择 1 个值,并循环遍历 df2 中的每一列。

df1 <- data.frame(fruit=c("Apple", "Orange", "Pear"), location = c("Japan", "China", "Nigeria"), price = c(32,53,12))
df2 <- data.frame(grocery = c("Durian", "Apple", "Watermelon"), place=c("Korea", "Japan", "Malaysia"), invoice = c("XD1", "XD2", "XD3"))

df1$source <- "DF1"
df2$source <- "DF2"

df1

   fruit location price source
1  Apple    Japan    32    DF1
2 Orange    China    53    DF1
3   Pear  Nigeria    12    DF1

df2  
     grocery    place invoice source
1     Durian    Korea     XD1    DF2
2      Apple    Japan     XD2    DF2
3 Watermelon Malaysia     XD3    DF2

这是我希望在名为 df3 的新数据帧下获得的输出。

df3
         grocery    place    invoice source
    1     fruit    location     NA    DF1

源列将允许用户识别各个列(水果/位置)的来源。 df3 的列名 = df2 的列名,而 row1 下的值 = df1 的列名。

Grocery 列与水果匹配,因为有一个匹配值,即“Apple”和“Japan”可以分别在 place 和 location 列中找到。

谢谢!

【问题讨论】:

  • 实际上并不清楚您的输出。这是否意味着您将始终只有 1 行输出?是否总是将df2 的列名作为df3 的列名,将df1 的列名作为第一行?
  • 你好 Ronak,是的,它只有 1 行。是的,df3 下的列名将始终来自 df2,而行值来自 df1
  • 类似setNames(data.frame(t(names(df1))), names(df2)) ?
  • 不,它必须遍历数据框以识别哪些列与哪些匹配,而不是通过 setNames 方法。您可以看到在 invoices 下为 NA,因为在 df1 中找不到 invoices 下的值
  • 这显然是可行的,但您应该定义“相似值”。如果您说“杂货”的价值与“水果”的价值相似,您是什么意思?一个匹配值就够了吗?还是两个?还是全部?或者如果一个变量包含“DF1”和“DF2”,另一个变量包含“DF3”和“DF4”,它们是否相似?a

标签: r


【解决方案1】:

这可能不是最佳解决方案,而是使用双 sapply 的一种方法(因为对于 df2 的每一列,我们希望在 df1 中找到相似的列)

sapply(names(df2), function(x) {
     temp <- sapply(names(df1), function(y) 
         if(any(match(df2[[x]], df1[[y]], nomatch = FALSE))) y else NA)
     ifelse(all(is.na(temp)), NA, temp[which.max(!is.na(temp))])
   }
)

# grocery     place     invoice     source 
# "fruit" "location"         NA         NA 

这将为您提供df2 中的所有列,其中matchdf1 中的列至少有一个值。然后,您可以稍后手动更改source 列,因为如果存在一行,您就知道它来自df1

【讨论】:

    【解决方案2】:

    做出改变。它很乱,但它有效。

    #create data frame of column combinations
    col_combos <- expand.grid(names(df1), names(df2))
    
    #identify like columns
    like_cols <- na.omit(col_combos[as.logical(apply(col_combos, 1, function(x) intersect(df1[, x[1] ],df2[, x[2] ]) > 1 )), ])
    
    #match like columns
    rbind(names(df2), as.character(like_cols$Var1)[match(names(df2), as.character(like_cols$Var2))])
    
         [,1]      [,2]       [,3]      [,4]    
    [1,] "grocery" "place"    "invoice" "source"
    [2,] "fruit"   "location" NA        NA   
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多