【问题标题】:Merge on multiple columns results in strange ordering合并多列会导致奇怪的排序
【发布时间】:2016-04-17 07:30:13
【问题描述】:

当两个数据框按数字列合并时(默认情况下)它们按该列排序作为数字。但是,如果将两个数字列用作by,那么它会导致不同的排序(实际上,数字列似乎被转换为字符串并如此排序)。这是预期的还是错误?

例如,考虑以下两个数据框:

A <- data.frame(a = 1:12, b = 1, x = runif(12))
B <- data.frame(a = 1:12, b = 1, y = runif(12))

然后,merge(A, B, by = 'a') 会生成一个数据框,其中包含 a 列,其值为 1、2、...、9、10、11、12(即预期的数字顺序)。然而,merge(A, B, by = c('a', 'b')) 会生成一个数据框,其中的列 a 的值为 1、10、11、12、2、3、...、8、9(即,与 sort(as.character(1:12)) 的排序相同)。

【问题讨论】:

标签: r sorting merge


【解决方案1】:

我猜它是一个功能而不是merge 的错误。

查看merge的源代码发现,在多列合并的情况下,'key'列在内部通过paste()组合成一个向量。

例如,数据框A 中的列a 和b 将由字符串"1\r1" "2\r1" "3\r1" "4\r1" "5\r1" "6\r1" "7\r1" "8\r1" "9\r1" "10\r1" "11\r1" "12\r1" 表示。

merge 使用此字符串对生成的数据框进行排序,这就是它以字母顺序结束的方式。

仅按一列合并的情况下,不需要使用paste,因此使用该列的原始类型进行排序。

这里是merge的相关源码(在R控制台不带括号运行merge.data.frame可以得到全文)

    if (l.b == 1L) {
        bx <- x[, by.x]
        if (is.factor(bx)) 
            bx <- as.character(bx)
        by <- y[, by.y]
        if (is.factor(by)) 
            by <- as.character(by)
    }
    else {
        if (!is.null(incomparables)) 
            stop("'incomparables' is supported only for merging on a single column")
        bx <- x[, by.x, drop = FALSE]
        by <- y[, by.y, drop = FALSE]
        names(bx) <- names(by) <- paste0("V", seq_len(ncol(bx)))
        bz <- do.call("paste", c(rbind(bx, by), sep = "\r"))
        bx <- bz[seq_len(nx)]
        by <- bz[nx + seq_len(ny)]
    }

【讨论】:

  • 谢谢。您的 cmets(和来源)完全解释了该行为。我同意这可能不是一个错误,因为merge 的文档对于行为应该是什么并不完全清楚(帮助说“默认情况下,行在公共列上按字典顺序排序”)。但是,在我看来,大多数人都会期望我期望的行为。是否值得将其作为 R 的错误/功能提升(或者像 merge 一样基本冻结)?
【解决方案2】:

使用dplyr包,我们可以得到如下结果

library("dplyr", lib.loc="~/R/win-library/3.2")

full_join(A, B, by=c("a", "b"))

     a b          x           y
    1   1 1 0.39907404 0.700782559
    2   2 1 0.84429488 0.600727090
    3   3 1 0.32232471 0.141495156
    4   4 1 0.74214210 0.262601640
    5   5 1 0.92944116 0.779255689
    6   6 1 0.10902661 0.001185645
    7   7 1 0.46336478 0.961711785
    8   8 1 0.58396008 0.211824751
    9   9 1 0.63126074 0.422233784
    10 10 1 0.09995935 0.179069642
    11 11 1 0.40832159 0.581116173
    12 12 1 0.48440814 0.004372634

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多