【发布时间】:2020-08-20 05:13:18
【问题描述】:
我经常发现人们以某种方式以未命名 未命名字符向量列表结束的问题,他们希望将它们逐行绑定到data.frame。这是一个例子:
library(magrittr)
data <- cbind(LETTERS[1:3],1:3,4:6,7:9,c(12,15,18)) %>%
split(1:3) %>% unname
data
#[[1]]
#[1] "A" "1" "4" "7" "12"
#
#[[2]]
#[1] "B" "2" "5" "8" "15"
#
#[[3]]
#[1] "C" "3" "6" "9" "18"
一种典型的方法是使用来自基础 R 的 do.call。
do.call(rbind, data) %>% as.data.frame
# V1 V2 V3 V4 V5
#1 A 1 4 7 12
#2 B 2 5 8 15
#3 C 3 6 9 18
也许效率较低的方法是使用来自 base R 的 Reduce。
Reduce(rbind,data, init = NULL) %>% as.data.frame
# V1 V2 V3 V4 V5
#1 A 1 4 7 12
#2 B 2 5 8 15
#3 C 3 6 9 18
但是,当我们考虑更现代的包(例如 dplyr 或 data.table)时,可能会立即想到的一些方法不起作用,因为向量未命名或不是列表。
library(dplyr)
bind_rows(data)
#Error: Argument 1 must have names
library(data.table)
rbindlist(data)
#Error in rbindlist(data) :
# Item 1 of input is not a data.frame, data.table or list
一种方法可能是在向量上使用set_names。
library(purrr)
map_df(data, ~set_names(.x, seq_along(.x)))
# A tibble: 3 x 5
# `1` `2` `3` `4` `5`
# <chr> <chr> <chr> <chr> <chr>
#1 A 1 4 7 12
#2 B 2 5 8 15
#3 C 3 6 9 18
但是,这似乎比需要的步骤更多。
因此,我的问题是将未命名 未命名字符向量列表绑定到data.frame行中的有效tidyverse或data.table方法是什么?聪明吗?
【问题讨论】:
-
附带说明,
Reduce(rbind,不能比do.call(rbind,更有效,因为do.call构造分配内存并复制数据一次,而Reduce构造重复分配新内存并重新复制所有以前的“rbinded”元素。 -
你说的很对。我没想到性能会如此糟糕,在 100,000 行上慢了 6,000 倍。我编辑了这个问题,称这是一种“效率较低的方法”。
标签: r dplyr data.table tidyverse purrr