编辑:已更新以包括新的答案。
我认为为这里的答案提供一个性能基准会很有帮助(见下文)。
使用 purrr::transpose()
方法似乎是明显的赢家,因为它既最快,又不会转换类型。
apply_method
和 Map_method
这两种方法会默默地转换类型,这可能会产生问题,因此我认为应优先考虑其他方法。
基准测试代码
library(microbenchmark)
library(tidyverse)
df <- tibble(x=rep("a", 1e4),
y=rnorm(1e4),
z=rnorm(1e4))
apply_method <- function(df){
apply(df, 1, as.list)
}
rowwise_method <- function(df){
df %>%
rowwise() %>%
group_split() %>%
map(~as.list(.x))
}
transpose_method <- function(df){
purrr::transpose(df)
}
Map_method <- function(df){
Map(as.list, data.frame(t(df)))
}
asplit_method <- function(df){
asplit(as_tibble(Map(as.list, df)), 1)
}
m <- microbenchmark(apply_method(df),
rowwise_method(df),
transpose_method(df),
Map_method(df),
asplit_method(df))
结果
Unit: milliseconds
expr min lq mean median uq max neval cld
apply_method(df) 40.241112 48.098472 58.87600 55.576808 65.852798 164.43654 100 c
rowwise_method(df) 209.235743 248.659766 279.77535 279.719901 310.229050 366.01956 100 e
transpose_method(df) 1.385084 1.962162 3.95705 3.013885 4.158427 41.28719 100 a
Map_method(df) 99.748096 124.712257 147.30464 138.841363 161.717376 283.76977 100 d
asplit_method(df) 22.444132 28.523968 38.90494 36.227208 44.920088 142.11396 100 b
演示静默类型转换的示例代码。
> apply_method(df)[1]
[[1]]
[[1]]$x
[1] "a"
[[1]]$y
[1] " 3.470658e-01"
[[1]]$z
[1] "-0.1900941676"
> rowwise_method(df)[1]
[[1]]
[[1]]$x
[1] "a"
[[1]]$y
[1] 0.3470658
[[1]]$z
[1] -0.1900942
> transpose_method(df)[1]
[[1]]
[[1]]$x
[1] "a"
[[1]]$y
[1] 0.3470658
[[1]]$z
[1] -0.1900942
> Map_method(df)[1]
$X1
$X1[[1]]
[1] "a"
$X1[[2]]
[1] " 3.470658e-01"
$X1[[3]]
[1] "-0.1900941676"
> asplit_method(df)[1]
[[1]]
[[1]]$x
[1] "a"
[[1]]$y
[1] -0.188605
[[1]]$z
[1] 0.5599404