【问题标题】:How can I rbind vectors matching their column names?如何 rbind 匹配其列名的向量?
【发布时间】:2013-06-02 11:45:45
【问题描述】:

rbind 在将向量绑定在一起时不检查列名:

l = list(row1 = c(10, 20), row2 = c(20, 10))
names(l$row1) = c("A", "B")
names(l$row2) = c("B", "A")
l
$row1
 A  B 
10 20 

$row2
 B  A 
20 10 

rbind(l$row1, l$row2)
      A  B
[1,] 10 20
[2,] 20 10

如何从多个列表元素中生成此矩阵,以确保列名在行间正确匹配:

      A  B
[1,] 10 20
[2,] 10 20

【问题讨论】:

    标签: r rbind


    【解决方案1】:

    reduce 是一个强大的功能,但有些不常用;这是另一种实现方式

    这将创建一个 rbind,如果存在与“NA”不匹配的列,将为它们生成。

    rbindedFrame = Reduce(custom_rbind,listofDataframes)  
    
    custom_rbind = function(x1,x2){
      c1 = setdiff(colnames(x1),colnames(x2))
      c2 = setdiff(colnames(x2),colnames(x1))
      for(c in c2){##Adding missing columns from 2 in 1
        x1[[c]]=NA
      }
      for(c in c1){##Similiarly ading missing from 1 in 2
        x2[[c]]=NA
      }
      x2 = x2[colnames(x1)]
      rbind(x1,x2)
    }
    }
    

    【讨论】:

      【解决方案2】:

      为什么不只是rbind(l$row1, l$row2[names(l$row1)])。也适用于数据帧。请注意,这将丢弃 l$row2 中未出现在 l$row1 中的列。

      【讨论】:

        【解决方案3】:

        似乎在 R 的当前版本(我有 3.3.0 版)中,rbind 能够连接两个具有相同名称列的数据集,即使它们的顺序不同。

           df1 <- data.frame(a = c(1:5), c = c(LETTERS[1:5]),b=c(11:15))
           df2 <- data.frame(a = c(6:10), b = c(16:20),c=c(LETTERS[6:10]))
           rbind(df1,df2)
            a c  b
        1   1 A 11
        2   2 B 12
        3   3 C 13
        4   4 D 14
        5   5 E 15
        6   6 F 16
        7   7 G 17
        8   8 H 18
        9   9 I 19
        10 10 J 20
        

        【讨论】:

        • 我发现只有在组合两个元素时才会这样。当尝试组合三个时,第三个被绑定而没有匹配的标签。有人可以确认吗?
        • R 版本 3.5.2 中的三个元素似乎可以正常工作:df1 &lt;- data.frame(a = c(1:5), c = c(LETTERS[1:5]),b=c(11:15)) df2 &lt;- data.frame(a = c(6:10), b = c(16:20),c=c(LETTERS[6:10])) df3 &lt;- data.frame(c = c(LETTERS[11:13]), a = c(11:13), b = c(21:23)) rbind(df1, df2, df3)
        【解决方案4】:

        smartbind() 将匹配列名并容忍缺失:

        library(gtools)
        do.call(smartbind,l)
              A  B
        row1 10 20
        row2 10 20
        

        【讨论】:

        • plyr::rbind.fill 是一个类似的解决方案。
        【解决方案5】:
        do.call(rbind, lapply(l, function(row) row[order(names(row))]))
        

        【讨论】:

          【解决方案6】:

          如果您首先将 l 的每个元素更改为数据框,rbind 将起作用:

          do.call("rbind", lapply(l, function(x) data.frame(as.list(x))))
          
                A  B
          row1 10 20
          row2 10 20
          

          【讨论】:

          • 射击。 Matthew Plourde 击败了我。
          • +1!并且还注意到这里有趣的是,来自data.table 的经典等效rbindlist 给出的答案与do.call(rbind,...) 不同
          • rbindlist 的一个不错的功能是能够很容易地用 NA 填充空值。
          【解决方案7】:

          你可以使用match:

          l <- list(row1 = setNames(1:3, c("A", "B", "C")),
                    row2 = setNames(1:3, c("B", "C", "A")),
                    row3 = setNames(1:3, c("C", "A", "B")))
          
          do.call(rbind, lapply(l, function(x) x[match(names(l[[1]]), names(x))]))
          

          结果:

               A B C
          row1 1 2 3
          row2 3 1 2
          row3 2 3 1
          

          【讨论】:

          • 查看下面@scs76 的答案;不再需要此解决方案。
          • 如果“行”有不同数量的元素,这仍然是需要的。
          猜你喜欢
          • 1970-01-01
          • 2021-05-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-14
          • 1970-01-01
          • 2018-12-31
          • 2014-02-08
          • 1970-01-01
          相关资源
          最近更新 更多