一种将不同长度的命名向量合并到 R 中的数据框(将名称信息保留为列名)的快速方法
Posted
技术标签:
【中文标题】一种将不同长度的命名向量合并到 R 中的数据框(将名称信息保留为列名)的快速方法【英文标题】:A fast way to merge named vectors of different length into a data frame (preserving name information as column name) in R 【发布时间】:2014-11-27 12:26:36 【问题描述】:我有一个命名向量列表 L。例如,第一个元素:
> L[[1]]
$event
[1] "EventA"
$time
[1] "1416355303"
$city
[1] "Los Angeles"
$region
[1] "California"
$Locale
[1] "en-GB"
当我 unlist
列表中的每个元素时,生成的向量看起来像这样(对于第一个 3 个元素):
> unlist(L[[1]])
event time city region Locale
"EventA" "1416355303" "Los Angeles" "California" "en-GB"
> unlist(L[[2]])
event time Locale
"EventB" "1416417567" "en-GB"
> unlist(L[[3]])
event properties.time
"EventM" "1416417569"
列表中有超过 50 万个元素,每个元素最多有 42 个这些特征/名称。我必须将它们合并到一个数据框中,考虑到它们的名称,并且并非所有它们都具有相同数量的特征或名称(在上面的示例中,V2 没有region
和city
的信息)。目前,我所做的是遍历整个列表:
df1 <- merge(stack(unlist(L[[1]])), stack(unlist(L[[2]])),
by = "ind", all = TRUE)
suppressWarnings(for (i in 3:length(L))
df1 <- merge(df1, stack(unlist(L[[i]])), by = "ind", all = TRUE)
)
df1 <- as.data.frame(t(df1))
对于上面的示例,这将返回:
V1 V2 V3 V4 V5
ind city event Locale region time
values.x Los Angeles EventA en-GB California 1416355303
values.y <NA> EventB en-GB <NA> 1416417567
values <NA> EventM <NA> <NA> 1416417569
这就是我想要的。但是,请记住列表的长度以及每次该命令:
df1 <- merge(df1, stack(unlist(L[[i]])), by = "ind", all = TRUE)
运行,加载整个数据帧(df1),循环需要很长时间。因此,我想知道是否有人知道更好/更快的编码方式。换句话说。给定一长串具有不同长度的命名向量,是否有一种快速方法将它们合并到如上所述的数据帧中。
例如,有没有使用foreach
和%dopar%
的方法?无论如何,欢迎任何更快的方法。
【问题讨论】:
【参考方案1】:我听说data.table
包非常快。 rbindlist
非常适合此列表。
library(data.table)
rbindlist(L, fill=TRUE)
# event time city region Locale
# 1: EventA 1416355303 Los Angeles California en-GB
# 2: EventB 1416417567 NA NA en-GB
# 3: EventM 1416417569 NA NA NA
【讨论】:
【参考方案2】:我不确定你为什么使用merge
。在我看来你应该简单地rbind
。
L <- list(list(event = "EventA", time = 1416355303,
city = "Los Angeles", region = "California",
Locale = "en-GB"),
list(event = "EventB", time = 1416417567,
Locale = "en-GB"),
list(event = "EventM", time = 1416417569))
library(plyr)
do.call(rbind.fill, lapply(L, as.data.frame))
# event time city region Locale
#1 EventA 1416355303 Los Angeles California en-GB
#2 EventB 1416417567 <NA> <NA> en-GB
#3 EventM 1416417569 <NA> <NA> <NA>
【讨论】:
您好。谢谢。唯一的问题是现实中的列表具有L[[i]]$event
和L[[i]]$properties
的结构。在属性中,我确实有L[[i]]$properties$time
、L[[i]]$properties$city
等等。因此,当我运行 as.data.frame 时,它会返回此 Error in data.frame(time = 1416355303, city = "Los Angeles", : arguments imply differing number of rows: 1, 0
。我将弄清楚如何更改列表的结构。再次感谢。
您有责任提供可重现的示例。将dput(L[1:3])
的输出添加到您的问题中。
我知道我知道,我只是如果我不解释每个细节会更容易和更简洁。我从你的回答中知道该怎么做。再次感谢。
对这里的do.call
感到好奇。看来rbind.fill(lapply(L, as.data.frame))
工作正常。【参考方案3】:
这是一个需要考虑的紧凑型解决方案:
library(reshape2)
dcast(melt(L), L1 ~ L2, value.var = "value")
# L1 city event Locale region time
# 1 1 Los Angeles EventA en-GB California 1416355303
# 2 2 <NA> EventB en-GB <NA> 1416417567
# 3 3 <NA> EventM <NA> <NA> 1416417569
【讨论】:
【参考方案4】:原帖是关于合并命名向量的。将上例中给出的前两个定义为向量:
>C1 <- c(event = "EventA", time = 1416355303,
city = "Los Angeles", region = "California",
Locale = "en-GB")
>C2 <- c(event = "EventB", time = 1416417567,
Locale = "en-GB")
如果您想合并它们并且可以放弃较长向量向量中的额外数据,那么您可以通过较短向量中的名称来索引较长向量
>C1 <- C1[names(C2)]
然后只需使用 rbind 或 cbind。 rbind 示例
>C1_C2 <- rbind(C1,C2)
>C1_C2
event time Locale
C1 "EventA" "1416355303" "en-GB"
C2 "EventB" "1416417567" "en-GB"
您可以合并最后两个步骤,但如果这样做会丢失第一个向量的名称
【讨论】:
以上是关于一种将不同长度的命名向量合并到 R 中的数据框(将名称信息保留为列名)的快速方法的主要内容,如果未能解决你的问题,请参考以下文章