一种将不同长度的命名向量合并到 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 没有regioncity 的信息)。目前,我所做的是遍历整个列表:

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]]$eventL[[i]]$properties 的结构。在属性中,我确实有L[[i]]$properties$timeL[[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 中的数据框(将名称信息保留为列名)的快速方法的主要内容,如果未能解决你的问题,请参考以下文章

将 R 中的数据帧连接/合并为向量类型单元格

需要一种将多列动态汇总为不同高度的合并单元格的方法

如何将命名向量作为行添加到数据框中,根据列名顺序重新排序?

熊猫在不同长度的列上合并两个数据框

R学习笔记 第三篇:数据框

合并 pandas 中列名不同且长度不同的两个数据框