我想基于列表的第一个元素上创建一个数据帧。具体而言,我有
names1 <- c("a", "b", "c")
dat1 <- data.frame(names1 =c("a", "b", "c", "f"),values= c("val1", 13, 11, 0))
dat1$values <- as.factor(dat1$values)
dat2 <- data.frame(names1 =c("a", "b", "x"),values= c(12, 10, 2))
dat2$values <- as.factor(dat2$values)
list1 <- list(dat1, dat2)
结果应与变量“名称”和所有的值,其各自的零部件清单比赛的新的数据帧:
a b c
val1 13 11
12 10 NA
一个选择是将循环通过list
(“list1的”),由“长”到filter
基于“名称”载体的“名称”栏,将其转换为一个单一的数据集而创建具有.id
标识列,spread
'宽”和删除‘GRP’列
library(tidyverse)
map_df(list1, ~ .x %>%
filter(names %in% !! names), .id = 'grp') %>%
spread(names, values) %>%
select(-grp)
# a b c
#1 25 13 11
#2 12 10 NA
或者另一种选择是将数据集与bind_rows
结合在一起,创造了一个分组标识“GRP”指定list
元素,通过选择具有“名称” filter
和vector
从“长”相匹配,只有“名称”列spread
行'宽'
bind_rows(list1, .id = 'grp') %>%
filter(names %in% !! names) %>%
spread(names, values)
注:这是最好不要使用保留的关键字指定对象名称(names
)。此外,为避免混淆,对象应该是从数据框对象的列名不同。
它只能与base R
也做。创建具有Map
组标识符,rbind
的list
元件以单个数据集,通过从“名称” subset
仅保留值vector
的行,以及从“长”到“宽” reshape
df1 <- subset(do.call(rbind, Map(cbind, list1,
ind = seq_along(list1))), names %in% .GlobalEnv$names)
reshape(df1, idvar = 'ind', direction = 'wide', timevar = 'names')[-1]
基R和dplyr
的混合。对于每一个列表元素,我们创建1行中的数据帧。使用dplyr
的rbind_list
将它们绑定排在一起,然后子集只有那些我们需要使用names
列。
library(dplyr)
rbind_list(lapply(list1, function(x)
setNames(data.frame(t(x$values)), x$names)))[names]
# a b c
# <dbl> <dbl> <dbl>
#1 25 13 11
#2 12 10 NA
无子输出看起来是这样的
rbind_list(lapply(list1, function(x) setNames(data.frame(t(x$values)), x$names)))
# a b c x
# <dbl> <dbl> <dbl> <dbl>
#1 25 13 11 NA
#2 12 10 NA 2
在基础R
t(sapply(list1, function(x) setNames(x$values, names)[match(names, x$names)]))
# a b c
# [1,] 25 13 11
# [2,] 12 10 NA
仅使用基础R
body <- do.call('rbind', lapply(list1, function(list.element){
element.vals <- list.element[['values']]
element.names <- list.element[['names']]
names(element.vals) <- element.names
return.vals <- element.vals[names]
if(all(is.na(return.vals))) NULL else return.vals
}))
df <- as.data.frame(body)
names(df) <- names
df
为了完整起见,这里是一个使用data.table和dcast()
一个rowid()
的方法:
library(data.table)
nam <- names1 # avoid name conflict with column name
rbindlist(list1)[names1 %in% nam, dcast(.SD, rowid(names1) ~ names1)][, names1 := NULL][]
a b c 1: val1 13 11 2: 12 10 <NA>
或者,更简洁,挑重塑后列:
library(data.table)
rbindlist(list1)[, dcast(.SD, rowid(names1) ~ names1)][, .SD, .SDcols = names1]