如何合并不等长的数据框列表?
How to merge dataframe lists of unequal length?
这个问题类似于。
我有一个 shiny
脚本,我在其中使用 fileImport
来允许用户导入可变数量的数据文件。然后将每个数据文件拆分为一个数据帧列表,并将这些作为列表导入。所以我有一个数据帧列表的列表。
输入数据文件有两种可能的格式,一种可能是 129 数据帧长,另一种可能是 67 - 其中 67 实际上是 129 的子集(因此所有 67 都出现在 129 中,但不是所有 129出现在 67)。然后我尝试按名称 rbind
数据帧。
一个可重现的例子:
# Some data
df.l1 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)))
df.l2 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)))
df.l3 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)),
df3 = data.frame(A = LETTERS[1:10],
B = rnorm(10, 15, 2)))
这适用于绑定长度相等的列表(例如 df.l1 和 df.l2)
df.two <- list(df.l1, df.l2)
list.merged <- do.call(function(...) Map(rbind, ...), df.two)
但在绑定具有可变长度的数据帧列表时失败。
df.three <- list(df.l1, df.l2, df.l3)
list.merged <- do.call(function(...) Map(rbind, ...), df.three)
报错:
Warning messages:
1: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter
2: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter
正如我上面所说,已经提出了类似的问题,但鉴于我尝试合并的列表数量可变,这种情况是独一无二的。非常感谢您的帮助!
为了稳健地处理这个问题,我会使用 dplyr::bind_rows
或 data.table::rbindlist
。首先绑定每个列表,然后在上层绑定:
tidyverse
版本:
library(dplyr)
bind_rows(lapply(df.three, bind_rows))
data.table
版本:
library(data.table)
rbindlist(lapply(df.three, rbindlist))
这不仅可以处理您意想不到的奇怪极端情况,而且比 do.call
.
快得多
根据评论进行编辑
试试这个:
library(purrr)
library(dplyr)
df_names <- unique(unlist(sapply(df.three, names)))
result <- list()
for (n in df_names) {
result[[n]] <- map(df.three, n)
}
map(result, dplyr::bind_rows)
这个问题类似于
我有一个 shiny
脚本,我在其中使用 fileImport
来允许用户导入可变数量的数据文件。然后将每个数据文件拆分为一个数据帧列表,并将这些作为列表导入。所以我有一个数据帧列表的列表。
输入数据文件有两种可能的格式,一种可能是 129 数据帧长,另一种可能是 67 - 其中 67 实际上是 129 的子集(因此所有 67 都出现在 129 中,但不是所有 129出现在 67)。然后我尝试按名称 rbind
数据帧。
一个可重现的例子:
# Some data
df.l1 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)))
df.l2 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)))
df.l3 <- list(df1 = data.frame(A = letters[1:10],
B = rnorm(10, 5, 1)),
df2 = data.frame(A = letters[11:20],
B = rnorm(10, 10, 2)),
df3 = data.frame(A = LETTERS[1:10],
B = rnorm(10, 15, 2)))
这适用于绑定长度相等的列表(例如 df.l1 和 df.l2)
df.two <- list(df.l1, df.l2)
list.merged <- do.call(function(...) Map(rbind, ...), df.two)
但在绑定具有可变长度的数据帧列表时失败。
df.three <- list(df.l1, df.l2, df.l3)
list.merged <- do.call(function(...) Map(rbind, ...), df.three)
报错:
Warning messages:
1: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter
2: In mapply(FUN = f, ..., SIMPLIFY = FALSE) :
longer argument not a multiple of length of shorter
正如我上面所说,已经提出了类似的问题,但鉴于我尝试合并的列表数量可变,这种情况是独一无二的。非常感谢您的帮助!
为了稳健地处理这个问题,我会使用 dplyr::bind_rows
或 data.table::rbindlist
。首先绑定每个列表,然后在上层绑定:
tidyverse
版本:
library(dplyr)
bind_rows(lapply(df.three, bind_rows))
data.table
版本:
library(data.table)
rbindlist(lapply(df.three, rbindlist))
这不仅可以处理您意想不到的奇怪极端情况,而且比 do.call
.
根据评论进行编辑
试试这个:
library(purrr)
library(dplyr)
df_names <- unique(unlist(sapply(df.three, names)))
result <- list()
for (n in df_names) {
result[[n]] <- map(df.three, n)
}
map(result, dplyr::bind_rows)