在R数据框中堆叠不平衡的数据

3

我有一些数据数组需要组合(堆叠)到一个数据框中进行分析。但是,某些个体的数据缺失。由于我事先不知道变量的完整列表,因此希望找到一种灵活的解决方案来堆叠这些数据。

示例:

a <- c(1,2,3,4,5,6)
names(a) <- c("A","B","C","D","E","F")
b <- c(1,1,1,1)
names(b) <- c("C","F","G","H")
c <- c(2,2,2)
names(c) <- c("A","D","H")

期望的结果:

result <- data.frame(rbind(
                    c(1,2,3,4,5,6, NA, NA),
                    c(NA, NA, 1, NA, NA, 1, 1 , 1),
                    c(2, NA, NA, 2, NA, NA, NA, 2) ) )

names(result) <- c("A","B","C","D","E","F","G","H") 
result

当第四行数据到来时,理想情况下,它应该被添加到现有的变量中(如果适用),在缺失值处显示NA,并在数据框中添加新变量(如果尚不存在)。可能可以编写一些复杂的(慢速)for循环,但必须有一个函数/包允许这样做。

4个回答

3
你可以尝试这个。
df.list = list(data.frame(a, ind = names(a)),
               data.frame(b, ind = names(b)),
               data.frame(c, ind = names(c)))

out = Reduce(function(...) merge(..., by = 'ind', all = T), df.list)

result = setNames(data.frame(t(out[,-1])), out$ind)

#   A  B  C  D  E  F  G  H
#a  1  2  3  4  5  6 NA NA
#b NA NA  1 NA NA  1  1  1
#c  2 NA NA  2 NA NA NA  2

2
今日免费次数已满, 请开通会员/明日再来
n <- unique(c(names(a), names(b), names(c)))
m <- t(sapply(list(a, b, c), function(x) x[match(n, names(x))]))
colnames(m) <- n

结果是:
print(m)
#      A  B  C  D  E  F  G  H
#[1,]  1  2  3  4  5  6 NA NA
#[2,] NA NA  1 NA NA  1  1  1
#[3,]  2 NA NA  2 NA NA NA  2

如果需要的话,您可以使用as.data.frame(m)将其转换为data.frame
或者,如果您先将向量放入列表中,那么可以这样做:
l <- list(a, b, c)
n <- unique(unlist(lapply(l, names)))
m <- t(sapply(l, function(x) x[match(n, names(x))]))
colnames(m) <- n

我接受这个答案,因为它简单、优雅,并且对我的目的最有帮助。 - Raynor

2

如果你只是处理命名的数字向量,那么下面是另一个基于R语言的选项。显而易见的区别是使用0代替NA,但如果需要的话,你也可以替换它们:

vec <- c(a, b, c)
rows <- rep(1:3, lengths(list(a, b, c)))
xtabs(vec ~ rows + names(vec))
#     names(vec)
# rows A B C D E F G H
#    1 1 2 3 4 5 6 0 0
#    2 0 0 1 0 0 1 1 1
#    3 2 0 0 2 0 0 0 2

这里是一个函数:
myFun <- function(...) {
  lst <- list(...)
  vec <- unlist(unname(lst))
  rows <- rep(seq_len(length(lst)), lengths(lst))
  xtabs(vec ~ rows + names(vec))
}

myFun(a, b, c)

1
你也可以使用dplyr包和bind_rows函数,但是你需要先将向量转换为data.frame
library(dplyr)
a <- c(1,2,3,4,5,6)
names(a) <- c("A","B","C","D","E","F")
b <- c(1,1,1,1)
names(b) <- c("C","F","G","H")
c <- c(2,2,2)
names(c) <- c("A","D","H")

### Dataframe with one row and vector name as column name
a <- as.data.frame(t(a))
b <- as.data.frame(t(b))
c <- as.data.frame(t(c))
## str(a)
## 'data.frame':    1 obs. of  6 variables:
##  $ A: num 1
##  $ B: num 2
##  $ C: num 3
##  $ D: num 4
##  $ E: num 5
##  $ F: num 6

bind_rows(a, b, c) ### or bind_rows(list(a, b, c))
##       A     B     C     D     E     F     G     H
##   (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl) (dbl)
## 1     1     2     3     4     5     6    NA    NA
## 2    NA    NA     1    NA    NA     1     1     1
## 3     2    NA    NA     2    NA    NA    NA     2

这个很好用,谢谢!但是,在我的应用程序中,当我有一个数据框包含1个TRUE/FALSE逻辑变量时,它就出问题了。 - Raynor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接