我可以在 dplyr 中加入 4 个以上的数据帧吗?

Can I join more than 4 dataframes in dplyr?

我正在尝试使用 dplyrleft_join 将 5 个模型的结果合并到一个数据框中以进行演示。每个模型结果都存在于自己的数据框中(用于演示目的的 dat1 到 dat5)。

*这是 home-brewed 似然函数的结果,因此无法通过 memisc 包中的 mtablestargazer

label1 <- paste0("var", 1:10)
beta1 <- 1:10
se1 <- 1:10*.01
p1 <- 1:10*.005

dat1 <- data.frame(label = label1
                   ,beta = beta1
                   ,se = se1
                   ,p = p1)


label2 <- paste0("var", 1:4)
beta2 <- 1:4
se2 <- 1:4*.01
p2 <- 1:4*.005

dat2 <- data.frame(label = label2
                   ,beta = beta2
                   ,se = se2
                   ,p = p2)


label3 <- paste0("var", 1:3)
beta3 <- 1:3
se3 <- 1:3*.01
p3 <- 1:3*.005

dat3 <- data.frame(label = label3
                   ,beta = beta3
                   ,se = se3
                   ,p = p3)

label4 <- paste0("var", 1:2)
beta4 <- 1:2
se4 <- 1:2*.01
p4 <- 1:2*.005

dat4 <- data.frame(label = label4
                   ,beta = beta4
                   ,se = se4
                   ,p = p4)

label5 <- paste0("var", 1)
beta5 <- 1
se5 <- 1*.01
p5 <- 1*.005

dat5 <- data.frame(label = label5
                   ,beta = beta5
                   ,se = se5
                   ,p = p5)

在常规 SQL 中,我希望 LEFT JOIN 函数的行为与在 sqldf 中的行为相同,如下所示。

sqldf(
"
select * 
from dat1
  left join dat2
    on dat1.label = dat2.label
  left join dat3
    on dat1.label = dat3.label
  left join dat4
    on dat1.label = dat4.label
"
)

#label beta   se     p label beta   se     p label beta   se     p label beta   se     p
#1   var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005
#2   var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010
#3   var3    3 0.03 0.015  var3    3 0.03 0.015  var3    3 0.03 0.015  <NA>   NA   NA    NA
#4   var4    4 0.04 0.020  var4    4 0.04 0.020  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#5   var5    5 0.05 0.025  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#6   var6    6 0.06 0.030  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#7   var7    7 0.07 0.035  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#8   var8    8 0.08 0.040  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#9   var9    9 0.09 0.045  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#10 var10   10 0.10 0.050  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA

忽略常规 SQL 中的重复列 headers,我可以在 dplyr 中复制相同的内容,如下所示。

dat1 %>% left_join(dat2,  by = c("label" = "label")) %>%
  left_join(dat3,  by = c("label" = "label")) %>%
  left_join(dat4,  by = c("label" = "label"))

#label beta.x se.x   p.x beta.y se.y   p.y beta.x se.x   p.x beta.y se.y   p.y
#1   var1      1 0.01 0.005      1 0.01 0.005      1 0.01 0.005      1 0.01 0.005
#2   var2      2 0.02 0.010      2 0.02 0.010      2 0.02 0.010      2 0.02 0.010
#3   var3      3 0.03 0.015      3 0.03 0.015      3 0.03 0.015     NA   NA    NA
#4   var4      4 0.04 0.020      4 0.04 0.020     NA   NA    NA     NA   NA    NA
#5   var5      5 0.05 0.025     NA   NA    NA     NA   NA    NA     NA   NA    NA
#6   var6      6 0.06 0.030     NA   NA    NA     NA   NA    NA     NA   NA    NA
#7   var7      7 0.07 0.035     NA   NA    NA     NA   NA    NA     NA   NA    NA
#8   var8      8 0.08 0.040     NA   NA    NA     NA   NA    NA     NA   NA    NA
#9   var9      9 0.09 0.045     NA   NA    NA     NA   NA    NA     NA   NA    NA
#10 var10     10 0.10 0.050     NA   NA    NA     NA   NA    NA     NA   NA    NA

在常规 SQL 中,我可以添加第 5 个 table 并获得预期的结果。

sqldf(
  "
select * 
from dat1
  left join dat2
    on dat1.label = dat2.label
  left join dat3
    on dat1.label = dat3.label
  left join dat4
    on dat1.label = dat4.label
  left join dat5
    on dat1.label = dat5.label
"
)

#label beta   se     p label beta   se     p label beta   se     p label beta   se     p label beta   se     p
#1   var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005
#2   var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  <NA>   NA   NA    NA
#3   var3    3 0.03 0.015  var3    3 0.03 0.015  var3    3 0.03 0.015  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#4   var4    4 0.04 0.020  var4    4 0.04 0.020  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#5   var5    5 0.05 0.025  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#6   var6    6 0.06 0.030  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#7   var7    7 0.07 0.035  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#8   var8    8 0.08 0.040  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#9   var9    9 0.09 0.045  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#10 var10   10 0.10 0.050  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA

dplyr中,虽然我似乎加入了dat5,但我最终放弃了dat3dat4,并重复了dat1dat2

dat1 %>% left_join(dat2,  by = c("label" = "label")) %>%
  left_join(dat3,  by = c("label" = "label")) %>%
  left_join(dat4,  by = c("label" = "label")) %>%
  left_join(dat5,  by = c("label" = "label")) 

#label beta.x se.x   p.x beta.y se.y   p.y beta.x se.x   p.x beta.y se.y   p.y beta   se     p
#1   var1      1 0.01 0.005      1 0.01 0.005      1 0.01 0.005      1 0.01 0.005    1 0.01 0.005
#2   var2      2 0.02 0.010      2 0.02 0.010      2 0.02 0.010      2 0.02 0.010   NA   NA    NA
#3   var3      3 0.03 0.015      3 0.03 0.015      3 0.03 0.015      3 0.03 0.015   NA   NA    NA
#4   var4      4 0.04 0.020      4 0.04 0.020      4 0.04 0.020      4 0.04 0.020   NA   NA    NA
#5   var5      5 0.05 0.025     NA   NA    NA      5 0.05 0.025     NA   NA    NA   NA   NA    NA
#6   var6      6 0.06 0.030     NA   NA    NA      6 0.06 0.030     NA   NA    NA   NA   NA    NA
#7   var7      7 0.07 0.035     NA   NA    NA      7 0.07 0.035     NA   NA    NA   NA   NA    NA
#8   var8      8 0.08 0.040     NA   NA    NA      8 0.08 0.040     NA   NA    NA   NA   NA    NA
#9   var9      9 0.09 0.045     NA   NA    NA      9 0.09 0.045     NA   NA    NA   NA   NA    NA
#10 var10     10 0.10 0.050     NA   NA    NA     10 0.10 0.050     NA   NA    NA   NA   NA    NA

我是否正确地将连接移植到 dplyr 中的 dat5

是否可以在 dplyr 中执行这么多连接?

EDIT1:我认为这与 () 不同。 Reduce 似乎解决了那里概述的问题。

在我的例子中,Reduce 产生的结果与上面最后一个代码块中显示的结果相同。

EDIT2:明确地说,我不关心多重 left-join 语法。我正在尝试确定为什么大于 4 个连接的行为与它们在 "regular" SQL.

中的行为不同

编辑 3:虽然我最初接受了下面@akrun 的回答,但我现在意识到以下输出:

lst <- lapply(mget(paste0("dat", 1:5)), transform, label2 = label)
suppressWarnings( Reduce(function(...) left_join(..., by = "label"), lst))

#label beta.x se.x   p.x label2.x beta.y se.y   p.y label2.y beta.x se.x   p.x label2.x beta.y se.y   p.y label2.y beta   se     p label2
#1   var1      1 0.01 0.005     var1      1 0.01 0.005     var1      1 0.01 0.005     var1      1 0.01 0.005     var1    1 0.01 0.005   var1
#2   var2      2 0.02 0.010     var2      2 0.02 0.010     var2      2 0.02 0.010     var2      2 0.02 0.010     var2   NA   NA    NA   <NA>
#  3   var3      3 0.03 0.015     var3      3 0.03 0.015     var3      3 0.03 0.015     var3      3 0.03 0.015     var3   NA   NA    NA   <NA>
#  4   var4      4 0.04 0.020     var4      4 0.04 0.020     var4      4 0.04 0.020     var4      4 0.04 0.020     var4   NA   NA    NA   <NA>
#  5   var5      5 0.05 0.025     var5     NA   NA    NA     <NA>      5 0.05 0.025     var5     NA   NA    NA     <NA>   NA   NA    NA   <NA>
#  6   var6      6 0.06 0.030     var6     NA   NA    NA     <NA>      6 0.06 0.030     var6     NA   NA    NA     <NA>   NA   NA    NA   <NA>
#  7   var7      7 0.07 0.035     var7     NA   NA    NA     <NA>      7 0.07 0.035     var7     NA   NA    NA     <NA>   NA   NA    NA   <NA>
#  8   var8      8 0.08 0.040     var8     NA   NA    NA     <NA>      8 0.08 0.040     var8     NA   NA    NA     <NA>   NA   NA    NA   <NA>
#  9   var9      9 0.09 0.045     var9     NA   NA    NA     <NA>      9 0.09 0.045     var9     NA   NA    NA     <NA>   NA   NA    NA   <NA>
#  10 var10     10 0.10 0.050    var10     NA   NA    NA     <NA>     10 0.10 0.050    var10     NA   NA    NA     <NA>   NA   NA    NA   <NA>

仍然不同于

sqldf(
  "
select * 
from dat1
  left join dat2
    on dat1.label = dat2.label
  left join dat3
    on dat1.label = dat3.label
  left join dat4
    on dat1.label = dat4.label
  left join dat5
    on dat1.label = dat5.label
"
)

#label beta   se     p label beta   se     p label beta   se     p label beta   se     p label beta   se     p
#1   var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005
#2   var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  <NA>   NA   NA    NA
#3   var3    3 0.03 0.015  var3    3 0.03 0.015  var3    3 0.03 0.015  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#4   var4    4 0.04 0.020  var4    4 0.04 0.020  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#5   var5    5 0.05 0.025  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#6   var6    6 0.06 0.030  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#7   var7    7 0.07 0.035  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#8   var8    8 0.08 0.040  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#9   var9    9 0.09 0.045  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#10 var10   10 0.10 0.050  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA

我还在输 dat3dat4...

编辑 4:不知道为什么,但我在下面的困惑可能部分是版本问题。 @akrun 的最终答案适用于 dplyr_0.4.3R version 3.3.0(显然是 Linux (Ubuntu) 和 PC)。

编辑 5:我认为 @akrun 和我都是 运行 dplyr 的开发版本(这就是为什么我第一次遇到问题 运行 @akrun 的我的 windows 机器上的解决方案正在使用生产 dplyr。)如前所述 here 此问题已在 dplyr. 的最新开发版本中得到解决

将数据集放入 list.

后,我们可以将 Reduceleft_join 一起使用
Reduce(function(...) left_join(..., by = "label"), mget(paste0("dat", 1:5)))

如果我们需要 label 列,我们可以再创建一列

lst <- lapply(mget(paste0("dat", 1:5)), transform, label2 = label)
lst[[1]]["label2"] <- NULL
res1 <- suppressWarnings( Reduce(function(...) left_join(..., by = "label"), lst))
res1
#   label beta.x se.x   p.x beta.y se.y   p.y label2.x beta.x.x se.x.x p.x.x label2.y beta.y.y se.y.y p.y.y label2.x.x beta   se     p
#1   var1      1 0.01 0.005      1 0.01 0.005     var1        1   0.01 0.005     var1        1   0.01 0.005       var1    1 0.01 0.005
#2   var2      2 0.02 0.010      2 0.02 0.010     var2        2   0.02 0.010     var2        2   0.02 0.010       var2   NA   NA    NA
#3   var3      3 0.03 0.015      3 0.03 0.015     var3        3   0.03 0.015     var3       NA     NA    NA       <NA>   NA   NA    NA
#4   var4      4 0.04 0.020      4 0.04 0.020     var4       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#5   var5      5 0.05 0.025     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#6   var6      6 0.06 0.030     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#7   var7      7 0.07 0.035     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#8   var8      8 0.08 0.040     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#9   var9      9 0.09 0.045     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#10 var10     10 0.10 0.050     NA   NA    NA     <NA>       NA     NA    NA     <NA>       NA     NA    NA       <NA>   NA   NA    NA
#   label2.y.y
#1        var1
#2        <NA>
#3        <NA>
#4        <NA>
#5        <NA>
#6        <NA>
#7        <NA>
#8        <NA>
#9        <NA>
#10       <NA>

这是来自第二个 sqldf 代码块的 OP 输出

res2
#   label beta   se     p label beta   se     p label beta   se     p label beta   se     p label beta   se     p
#1   var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005  var1    1 0.01 0.005
#2   var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  var2    2 0.02 0.010  <NA>   NA   NA    NA
#3   var3    3 0.03 0.015  var3    3 0.03 0.015  var3    3 0.03 0.015  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#4   var4    4 0.04 0.020  var4    4 0.04 0.020  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#5   var5    5 0.05 0.025  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#6   var6    6 0.06 0.030  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#7   var7    7 0.07 0.035  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#8   var8    8 0.08 0.040  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#9   var9    9 0.09 0.045  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA
#10 var10   10 0.10 0.050  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA  <NA>   NA   NA    NA


dim(res1)
#[1] 10 20
dim(res2)
#[1] 10 20