【问题标题】:Join data frames over a third dimension by row/column names通过行/列名在三维上连接数据框
【发布时间】:2018-09-12 12:25:10
【问题描述】:

我有任意数量的数据框,带有行名和列名。

我的目标是使用行/列名称作为连接键在三维上连接这些数据框,即我希望结果是一个命名的三维数组。

我的问题是我不想按位置加入他们,而是通过他们的行/列名。

我知道我可以使用 abind() 沿任何所需维度连接数组,但 abind 连接数据位置,而不是通过暗名。

在 sql 术语中,我想要一个使用行/列名称作为连接键的完全连接,但沿第三个维度。

这里有一个只有两个数据框的可重现的小例子:

first <- data.frame(one=c(1,2), two=c(3,4), row.names = c("one", "two"))
second <- data.frame(one=c(10,20), three=c(50,60), row.names = c("one", "three"))
result <- someMagicFunction(first, second)

我想要的“结果”对象的输出是:

result <- array(data=c(1, 2, NA, 3, 4, NA, NA, NA, NA,
                       10, NA, 20, NA, NA, NA, 50, NA, 60), 
                dim = c(3, 3, 2), 
                dimnames = list(
                  c("one", "two", "three"),
                  c("one", "two", "three"),
                  c("first", "second")))
> result
, , first

      one two three
one     1   3    NA
two     2   4    NA
three  NA  NA    NA

, , second

      one two three
one    10  NA    50
two    NA  NA    NA
three  20  NA    60

我自己编写了一个函数来完成任务,但我想知道是否已经有任何内置函数可以做到这一点。

谢谢!

【问题讨论】:

  • 使用arrays有什么特别的原因吗?我的意思是加入列名和行名是很不寻常的,或者?
  • 为什么不只是重新排列行/列,使它们处于适当的顺序,然后使用abind

标签: r


【解决方案1】:
library(abind)
library(magrittr)

in.dfs <- list(first, second)

cols <- unique(unlist(lapply(in.dfs, names)))
rows <- unique(unlist(lapply(in.dfs, rownames)))

allNA <- 
  matrix(NA, length(cols), length(rows)) %>% 
    `colnames<-`(cols) %>% 
    `rownames<-`(rows)

lapply(in.dfs, function(df){
  allNA[rownames(df), names(df)] <- as.matrix(df)
  allNA
}) %>% 
  list(along = 3) %>% 
  do.call(what = abind)

结果

# , , 1
# 
#       one two three
# one     1   3    NA
# two     2   4    NA
# three  NA  NA    NA
# 
# , , 2
# 
#       one two three
# one    10  NA    50
# two    NA  NA    NA
# three  20  NA    60

【讨论】:

    【解决方案2】:

    不清楚“数组”的事情。我会这样解决它:

    如果您正在寻找快速基础优雅的解决方案:

    数据:

    first <- data.frame(one=c(1,2), two=c(3,4), row.names = c("one", "two"))
    second <- data.frame(one=c(10,20), three=c(50,60), row.names = c("one", "three"))
    
    l <- list(first, second)
    

    代码:

    dn <- unique(c(sapply(l, names)))
    
    model<-as.data.frame(structure(rep(NA,length(dn)^2), .Dim = c(length(dn), length(dn)), .Dimnames = list(dn, dn)))
    
    lapply(l, function(el){model[names(el),names(el)] <- el;model})
    

    结果:

    [[1]]
          one two three
    one     1   3    NA
    two     2   4    NA
    three  NA  NA    NA
    
    [[2]]
          one two three
    one    10  NA    50
    two    NA  NA    NA
    three  20  NA    60
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-03
      • 2018-08-01
      • 1970-01-01
      • 2017-03-23
      • 2022-09-28
      • 1970-01-01
      相关资源
      最近更新 更多