【问题标题】:R merge() rbinds instead of mergingR merge() rbinds 而不是合并
【发布时间】:2020-12-18 02:59:04
【问题描述】:

我在 R 中遇到了我无法理解的 merge() 行为。它似乎根据列中是否包含一个或多个唯一值来合并或重新绑定数据帧。

a1 <- data.frame (A = c (1, 1))
a2 <- data.frame (A = c (1, 2))

# > merge (a1, a1)
#   A
# 1 1
# 2 1
# 3 1
# 4 1

# > merge (a2, a2)
#   A
# 1 1
# 2 2

在这两种情况下,后者都是我所期望和想要的结果。我还尝试了多列,以及字符而不是数字,结果是相同的:多个值导致合并,一个唯一值导致 rbinding。

【问题讨论】:

    标签: r dataframe merge rbind


    【解决方案1】:

    在第一种情况下,每行匹配两行,因此输出中有 2x2=4 行;在第二种情况下,每行匹配一行,因此输出中有 2 行。

    要匹配行号,请使用:

    merge(a1, a1, by = 0)
    ##   Row.names A.x A.y
    ## 1         1   1   1
    ## 2         2   1   1
    

    或者匹配行号并且只返回左边的实例:

    library(sqldf)
    
    sqldf("select x.* from a1 x left join a1 y on x.rowid = y.rowid")
    ##   A
    ## 1 1
    ## 2 1
    

    或匹配行号并返回两个实例:

    sqldf("select x.A A1, y.A A2 from a1 x left join a1 y on x.rowid = y.rowid")
    ##   A1 A2
    ## 1  1  1
    ## 2  1  1
    

    【讨论】:

    • 谢谢。您是否知道我是否可以在不借助任何外部软件包的情况下达到相同的结果?
    • 这就是第一个示例显示的内容。如果您只需要列的子集,则可以在合并后将它们子集。
    • 我在想一个更干净的结果,比如使用 sqldf 的结果,只是没有使用它。
    • 之后您需要修复它。
    【解决方案2】:

    文档中详细说明了该行为,但基本上,merge() 默认情况下会希望给您一个data.frame,其中的列取自两个原始 dfs。它将通过所有公共列的唯一值合并两者的行。

    df1 <- data.frame(a = 1:3, b = letters[1:3])
    df2 <- data.frame(a = 1:5, c = LETTERS[1:5])
    df1
      a b
    1 1 a
    2 2 b
    3 3 c
    df2
      a c
    1 1 A
    2 2 B
    3 3 C
    4 4 D
    5 5 E
    merge(df1, df2)
      a b c
    1 1 a A
    2 2 b B
    3 3 c C
    

    在您的第一个示例中发生的情况是 merge() 想要通过 A 列组合您的两个数据帧的行,但由于两个 dfs 中的两行相同,它无法确定哪一行与之合并,因此它会创建所有可能的组合。

    在您的第二个示例中,您没有这个问题,因此合并是明确的。 1 行将合并在一起,2 行也将合并在一起。

    当您的 dfs 中有多个列时,情况会更加明显:

    案例一:

    > df1 <- data.frame(a = c(1, 1), b = letters[1:2])
    > df2 <- data.frame(a = c(1, 1), c = LETTERS[1:2])
    > df1
      a b
    1 1 a
    2 1 b
    > df2
      a c
    1 1 A
    2 1 B
    > merge(df1, df2)
      a b c
    1 1 a A
    2 1 a B
    3 1 b A
    4 1 b B
    

    案例 2:

    > df1 <- data.frame(a = c(1, 2), b = letters[1:2])
    > df2 <- data.frame(a = c(1, 2), c = LETTERS[1:2])
    > df1
      a b
    1 1 a
    2 2 b
    > df2
      a c
    1 1 A
    2 2 B
    > merge(df1, df2)
      a b c
    1 1 a A
    2 2 b B
    

    【讨论】:

    • 谢谢。我阅读了文档,但从那里没有理解;我想我现在明白了。你知道解决方法吗?类似于合并by="row.names()",但结果中没有Row.names 列,并且A 列没有加倍?
    • @KamilS。来自文档,第 2 段,最后一句:“如果有多个匹配项,则所有可能的匹配项各贡献一行。有关“匹配”的确切含义,请参阅匹配。。所以在问题示例a1 中的第一个 1 匹配 a1 中的两个 1,第二个 1 匹配两个 1。
    • @KamilS 我不太确定我理解你想要什么样的结果。如果您想要与第一个答案(由 G. Grothendieck 编写)中的代码产生的输出相同的输出,只是没有行名,您可以简单地执行 merge(df1, df2, by = 0)[ , -1]。但是,这将复制公共列。
    • @MilanValášek 我想在 G. Grothendieck 的回答中得到第二个结果,基本上我希望 merge(a1,a1)a1 相同。只有我想在不使用任何外部包的情况下获得它。
    • 潜在的附加列应该怎么办?比如说,你有两个数据框,就像我的“案例 1”中的那个一样。应该如何治疗?
    猜你喜欢
    • 1970-01-01
    • 2020-11-01
    • 2021-09-04
    • 2014-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-15
    相关资源
    最近更新 更多