【问题标题】:Incorrect behavior with dplyr's left_join?dplyr 的 left_join 行为不正确?
【发布时间】:2014-11-09 15:44:28
【问题描述】:

这不是故意的吗?这是dplyr 功能的其他部分发生的事情吗?我应该担心吗?我喜欢这种表现,讨厌data.table 语法。是否有替代 dplyrdata.table 目前可以安全使用并且仍然具有高性能的替代品?

A <- structure(list(ORDER = c(30305720L, 30334659L, 30379936L, 
                     30406397L, 30407697L, 30431950L), 
                    COST = c("0", "", "11430.52", "20196.279999999999", "0", "10445.99")), 
               .Names = c("ORDER", "COST"), 
               row.names = c(NA, 6L), 
               class = "data.frame")

B <- structure(list(ORDER = c(30334659, 30379936, 30406397, 30407697, 30431950), 
                    AREA = c(0, 2339, 2162, 23040, 475466)), 
               .Names = c("ORDER", "AREA"), 
               row.names = c(4L, 8L, 11L, 12L, 15L), 
               class = c("tbl_df", "tbl", "data.frame"))

垃圾结果:

left_join(A, B)
  ORDER    COST                 AREA
1 30305720                  0   NA
2 30334659                      NA
3 30379936           11430.52   NA
4 30406397 20196.279999999999   NA
5 30407697                  0   NA
6 30431950           10445.99   NA

效果:

merge(A, B, all.x=T, all.y=F)
     ORDER               COST   AREA
1 30305720                  0     NA
2 30334659                         0
3 30379936           11430.52   2339
4 30406397 20196.279999999999   2162
5 30407697                  0  23040
6 30431950           10445.99 475466

【问题讨论】:

  • 我使用的是 R 版本 3.1。
  • 请注意,这似乎在github.com/hadley/dplyr/issues/601
  • 请注意,data.table 语法 setDT(A);setDT(B);setkey(A,ORDER);setkey(B,ORDER);A[B] 用于提供“有效结果”。 data.table 使键/分组在机器容差范围内相等。
  • 如果合并 did 失败并给您错误的结果,而您将它们显示在任何地方,那将是 您的 错。

标签: r merge left-join dplyr


【解决方案1】:

前几天我发布了类似的内容。我认为您需要做的是将 ORDER 作为数字(或者可能相反)。 A 有 ORDER 有整数。但是 B 有 ORDER 作为数字。目前,dplyr 要求您在同一类中有分组变量。我收到了一位 SO 用户的评论,说这是 Hadley 和他的团队现在一直在做的事情。以后会修复这个问题。

A$ORDER <- as.numeric(A$ORDER)
left_join(A,B, by = "ORDER")

     ORDER               COST   AREA
1 30305720                  0     NA
2 30334659                         0
3 30379936           11430.52   2339
4 30406397 20196.279999999999   2162
5 30407697                  0  23040
6 30431950           10445.99 475466

更新 和 thelatemail 交换了 cmets 之后,我决定在这里添加更多的观察。

案例 1:将 ORDER 视为数字

A$ORDER <- as.numeric(A$ORDER)

> left_join(A,B, by = "ORDER")
     ORDER               COST   AREA
1 30305720                  0     NA
2 30334659                         0
3 30379936           11430.52   2339
4 30406397 20196.279999999999   2162
5 30407697                  0  23040
6 30431950           10445.99 475466

> left_join(B,A, by = "ORDER")
Source: local data frame [5 x 3]

     ORDER   AREA               COST
1 30334659      0                   
2 30379936   2339           11430.52
3 30406397   2162 20196.279999999999
4 30407697  23040                  0
5 30431950 475466           10445.99

如果你在 A 和 B 中都有 ORDER 作为整数,那也可以。

案例 2:将 ORDER 视为整数和数字

> left_join(A,B, by = "ORDER")
     ORDER               COST AREA
1 30305720                  0   NA
2 30334659                      NA
3 30379936           11430.52   NA
4 30406397 20196.279999999999   NA
5 30407697                  0   NA
6 30431950           10445.99   NA

> left_join(B,A, by = "ORDER")
Source: local data frame [5 x 3]

     ORDER   AREA               COST
1 30334659      0                   
2 30379936   2339           11430.52
3 30406397   2162 20196.279999999999
4 30407697  23040                  0
5 30431950 475466           10445.99

正如 thelatemail 所建议的,整数/数字组合不起作用。但数字/整数组合有效。

鉴于这些观察结果,目前在 group-by 变量中保持一致是安全的。或者,merge() 是要走的路。它可以处理整数和数字。

> merge(A,B, by = "ORDER", all = TRUE)
     ORDER               COST   AREA
1 30305720                  0     NA
2 30334659                         0
3 30379936           11430.52   2339
4 30406397 20196.279999999999   2162
5 30407697                  0  23040
6 30431950           10445.99 475466 

> merge(B,A, by = "ORDER", all = TRUE)
     ORDER   AREA               COST
1 30305720     NA                  0
2 30334659      0                   
3 30379936   2339           11430.52
4 30406397   2162 20196.279999999999
5 30407697  23040                  0
6 30431950 475466           10445.99

UPDATE2(截至 2014 年 11 月 8 日)

我正在使用 dplyr(dplyr_0.3.0.9000) 的开发版,您可以从 Github 下载。 上述问题现已解决。

left_join(A,B, by = "ORDER")
#     ORDER               COST   AREA
#1 30305720                  0     NA
#2 30334659                         0
#3 30379936           11430.52   2339
#4 30406397 20196.279999999999   2162
#5 30407697                  0  23040
#6 30431950           10445.99 475466

【讨论】:

  • +1 - 被打败了。我仍然对为什么 left_join(B, A) 似乎工作正常感到困惑。
  • @thelatemail 这是一个有趣的观察。如果是这样,那么这是一个真正的错误吗?
  • 乍一看,我会说是。整数/数字连接失败但数字/整数连接成功对我来说是不一致的。
  • @thelatemail 我将根据所有观察结果更新我的答案。这对社区很有用。
【解决方案2】:

来自dplyr documentation

left_join()

返回来自x 的所有行,以及来自xy 的所有列。 x 中与 y 不匹配的行将在新列中具有 NA 值。如果xy 之间有多个匹配项,则返回匹配项的所有组合。

semi_join()

返回来自x 的所有行,其中y 中存在匹配值,只保留来自x 的列。

半连接与内连接不同,因为内连接将为y 的每个匹配行返回一行x,其中半连接永远不会重复x 的行。

semi_join() 对您来说是一个有价值的选择吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多