【问题标题】:r multiple joins from list of data frames of differing lengths and differing keysr 来自不同长度和不同键的数据帧列表的多个连接
【发布时间】:2018-01-25 21:47:04
【问题描述】:

假设我有这个数据框列表:

library(tidyverse)
df_list <- list(data.frame(cheese = c("ex","ok","bd"), 
                          cheese_val = c(3:1), 
                          stringsAsFactors = F),
               data.frame(egg = c("great","good","bad", "eww"), 
                          egg_val = c(4:1),
                          stringsAsFactors = F),
               data.frame(milk = c("good","bad"), 
                          milk_val = c(2:1), 
                          stringsAsFactors = F))

我有这个核心数据集:

core_dat <- data.frame(cheese = c("ex","ok","ok", "bd", "ok"), 
                      egg = c("great", "bad", "bad", "eww", "great"), 
                      milk = c("good", "good", "good", "bad", "good"), 
                      stringsAsFactors = F)

我想让core_datdf_list 的每个元素单独连接。

然后我尝试了这个:

for(i in 1:length(df_list)) {
  gg<-core_dat %>% 
    left_join(df_list[[i]], by = names(df_list[[i]][1]), copy = T)
}

它运行但仅将连接应用于milk 列,因此core_dat 中唯一的附加列是milk_val,但我预计也会看到cheese_valegg_val

我怀疑这里有比 for 循环更合适的选项,我正在寻找建议。请注意,我的实际数据集比这个小例子有更多的 df。

我不应该期望生成的数据框,在本例中为 gg,总共包含 6 列(3 个标准名称 + 3 个带有“val”后缀的列),因此它看起来像这样的打印版本:

data.frame(cheese = c("ex","ok","ok", "bd", "ok"), 
                      egg = c("great", "bad", "bad", "eww", "great"), 
                      milk = c("good", "good", "good", "bad", "good"), 
                      chees_val = c(3, 2, 2, 1, 2), 
                      egg_val = c(4, 2, 2, 1, 4), 
                      milk_val = c(2, 2, 2, 1, 2))

我在这里看到了许多“多重连接”的答案,但没有一个与我在这里想要完成的任务完全一致(不同的键列、不同的数据长度)。

【问题讨论】:

  • 试试 map(df_list, left_join, core_dat)right_join 不确定预期的输出是什么
  • 你可以做lapply(df_list,merge,core_data)
  • @missuse - map 没有提供想要的结果:我更新了一些问题。
  • 我们能看到你想要的输出吗?这个例子?

标签: r list dataframe left-join


【解决方案1】:

您可以使用map 获取已连接数据框的列表,然后使用reduce 将它们全部连接在一起。

map(df_list, right_join, rownames_to_column(core_dat)) %>%
  reduce(full_join)
# Joining, by = "cheese"
# Joining, by = "egg"
# Joining, by = "milk"
# Joining, by = c("cheese", "rowname", "egg", "milk")
# Joining, by = c("cheese", "rowname", "egg", "milk")
#   cheese cheese_val rowname   egg milk egg_val milk_val
# 1     ex          3       1 great good       4        2
# 2     ok          2       2   bad good       2        2
# 3     ok          2       3   bad good       2        2
# 4     bd          1       4   eww  bad       1        1
# 5     ok          2       5 great good       4        2

【讨论】:

  • 我对超过原始core_data qty of 5 的记录数量感到困惑。
  • 我添加了行 ID 以使其具有所需的行数。
  • 这也适用于我的小例子我的 43 变量版本 - 谢谢!
【解决方案2】:

这应该会给出所需的输出:

Reduce(merge,c(df_list,list(core_dat)))
  cheese   egg milk cheese_val egg_val milk_val
1     bd   eww  bad          1       1        1
2     ex great good          3       4        2
3     ok   bad good          2       2        2
4     ok   bad good          2       2        2
5     ok great good          2       4        2

【讨论】:

  • 这适用于我的小例子,但在我的原始数据中我的内存不足。
  • 您的数据有多大?这是一个基本的 R 解决方案。尝试dplyr 解决方案。我不能写,因为它已经给出了