library(purrr)
library(tibble)
library(dplyr)
开始数据框的列表
lst <- list(df1 = data.frame(X.1 = as.character(1:2),
heading = letters[1:2]),
df2 = data.frame(X.32 = as.character(3:4),
another.topic = paste("Line ", 1:2)))
lst
#> $df1
#> X.1 heading
#> 1 1 a
#> 2 2 b
#>
#> $df2
#> X.32 another.topic
#> 1 3 Line 1
#> 2 4 Line 2
预期的 "组合 "数据帧,新的一致的变量名,旧的变量名在每个组成数据帧的第一行。
#> id h1 h2
#> 1 df1 X.1 heading
#> 2 df1 1 a
#> 3 df1 2 b
#> 4 df2 X.32 another.topic
#> 5 df2 3 Line 1
#> 6 df2 4 Line 2
add_row
需要 "名称-值对,传递给tibble()。只能为.data中已经存在的列定义值,未设置的列将得到一个NA值。"
这也是我认为我这样做的目的。
df_nms <-
map(lst, names) %>%
map(set_names)
#> $df1
#> X.1 heading
#> "X.1" "heading"
#>
#> $df2
#> X.32 another.topic
#> "X.32" "another.topic"
但我不能把最后一点绑起来,用一个purrr函数把名字加到每个数据框的头部。我已经尝试了许多变化,用 map2
和 pmap
最接近我目前所能得到的(如果我对待 add_row
作为一个公式,在前面加上 ~
并去除 .y
我得到了一个新的第一行填充的NAs)。) 我想我缺少了如何将名字-值对传递给add_row函数的方法。
map2(lst, df_nms, add_row(.x, .y, .before = 1)) %>%
map(set_names, c("h1", "h2")) %>%
map_dfr(bind_rows, .id = "id")
#> Error in add_row(.x, .y, .before = 1): object '.x' not found
如果能给我一个解决最后一步的指针,我将非常感激。
下面是一个使用 map
, rbindlist
从 data.table
和一些基础R函数。
library(purrr)
library(dplyr)
library(data.table)
map(lst, ~ as.data.frame(unname(rbind(colnames(.x),as.matrix(.x))))) %>%
rbindlist(idcol = "id")
# id V1 V2
#1: df1 X.1 heading
#2: df1 1 a
#3: df1 2 b
#4: df2 X.32 another.topic
#5: df2 3 Line 1
#6: df2 4 Line 2
或者我们可以使用 map_df
如果我们使用 colnames<-
:
map_df(lst, ~ as.data.frame(rbind(colnames(.x),as.matrix(.x))) %>%
`colnames<-`(.,paste0("h",seq(1,dim(.)[2]))), .id = "id")
# id h1 h2
#1 df1 X.1 heading
#2 df1 1 a
#3 df1 2 b
#4 df2 X.32 another.topic
#5 df2 3 Line 1
#6 df2 4 Line 2
这里的关键是:
as.matrix
以消除因子字符的不兼容性。unname
或将其与 colnames<-
idcols =
或 .id =
功能来获取列表的名称作为一列。不太清楚如何通过 purrr
地图功能,但这里有一个替代方案。
library(dplyr)
bind_rows(lapply(lst, function(i){d1 <- as.data.frame(matrix(names(i), ncol = ncol(i)));
rbind(d1, setNames(i, names(d1)))}), .id = 'id')
# id V1 V2
#1 df1 X.1 heading
#2 df1 1 a
#3 df1 2 b
#4 df2 X.32 another.topic
#5 df2 3 Line 1
#6 df2 4 Line 2
我修改了一下你的样本数据,设置为 stringsAsFactors
到 FALSE
中创建data.framework时 lst
.
下面是一个解决方案,使用 data.table::rbindlist()
.
#sample data
lst <- list(df1 = data.frame(X.1 = as.character(1:2),
heading = letters[1:2],
stringsAsFactors = FALSE), # !! <--
df2 = data.frame(X.32 = as.character(3:4),
another.topic = paste("Line ", 1:2),
stringsAsFactors = FALSE) # !! <--
)
DT <- data.table::rbindlist( lapply( lst, function(x) rbind( names(x), x ) ),
use.names = FALSE, idcol = "id" )
setnames(DT, names( lst[[1]] ), c("h1", "h2") )
# id h1 h2
# 1: df1 X.1 heading
# 2: df1 1 a
# 3: df1 2 b
# 4: df2 X.32 another.topic
# 5: df2 3 Line 1
# 6: df2 4 Line 2