R 创建数据帧,基于列表的第一个元素进行匹配
我想基于列表的第一个元素创建一个数据框。具体来说,我有R 创建数据帧,基于列表的第一个元素进行匹配,r,list,dataframe,match,data.table,R,List,Dataframe,Match,Data.table,我想基于列表的第一个元素创建一个数据框。具体来说,我有 一个包含变量的向量(名称1) 一个包含两个变量(一些变量1和值)的列表 最终产品应该是一个带有“names1”的data.frame,其中包含的行数与匹配的案例数相同 如果特定列表和向量之间不匹配,则应为NA 值也可以是因子或字符串 names1 <- c("a", "b", "c") dat1 <- data.frame(names1 =c("a", "b", "c", "f"),values= c("val1", 13, 1
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)
一个选项是循环通过
列表
('list1'),过滤器
基于'names'向量的'names'列,将其转换为单个数据集,同时创建具有.id
,排列
的标识列,从'long'到'wide',并删除'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
绑定在一起,创建一个分组id“grp”来指定列表
元素,通过只选择与“name”向量相匹配的“names”列以及从“long”到“wide”的排列来过滤行
bind_rows(list1, .id = 'grp') %>%
filter(names %in% !! names) %>%
spread(names, values)
注意:最好不要使用保留关键字来指定对象名称(名称
)。此外,为了避免混淆,对象应该与dataframe对象的列名不同
也可以仅使用base R
完成此操作。使用映射
,rbind
将列表
元素添加到单个数据集,子集
行创建组标识符,方法是仅保留“名称”向量
中的值,并将形状从“长”改为“宽”
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]
df1基本R和dplyr的混合体
。对于每个列表元素,我们创建一个包含1行的数据框。使用dplyr
的rbind\u列表
行将它们绑定在一起,然后使用名称
只对需要的列进行子集划分
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
库(dplyr)
rbind_列表(lappy)(列表1,函数(x)
集合名(data.frame(t(x$value)),x$names))[名称]
#a、b、c
#
#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
rbind_列表(lappy(列表1,函数(x)集合名(data.frame(t(x$value)),x$names)))
#a b c x
#
#1251311 NA
#2 12 10 NA 2
仅使用基本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
底部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
为了完整起见,下面是一种使用dcast()
和rowid()
的方法:
Adata.table
解决方案:库(data.table);rbindlist(lappy(list1,函数(x)setNames(transpose(x)[2,],x$names)),use.names=TRUE,fill=TRUE)[,.SD,.SDcols=(a:c)]
。非常感谢,这非常有效——还有解决因子值的方法吗?(如果值是一个因子)?对于因子也可以这样做吗?(例如,如果值是因子还是字符串?)我意识到它是有效的,但只有当数值和因子值不混合时才有效!非常感谢,阿克伦!!!太棒了@托比亚希,谢谢。这有点奇怪。您可以尝试在%!!名称中使用过滤器(如.character(names)%
t(sapply(list1, function(x) setNames(x$values, names)[match(names, x$names)]))
# a b c
# [1,] 25 13 11
# [2,] 12 10 NA
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]