假设您想要将矩阵转换为列表,其中列表的每个元素都包含一列。list()
或as.list()
显然不会工作,到目前为止,我使用了一个使用tapply
行为的黑客:
x <- matrix(1:10,ncol=2)
tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i)
我对此并不完全满意。有人知道我忽略的更干净的方法吗?
(为了创建一个由行填充的列表,显然可以将代码更改为:
tapply(x,rep(1:nrow(x),ncol(x)),function(i)i)
)
发布于 2011-07-26 07:17:20
为了给猫设置皮肤,将数组视为一个向量,就好像它没有dim属性一样:
split(x, rep(1:ncol(x), each = nrow(x)))
发布于 2011-07-26 03:41:02
Gavin的回答简单而优雅。但是如果有很多列,一个更快的解决方案应该是:
lapply(seq_len(ncol(x)), function(i) x[,i])
在下面的示例中,速度差为6倍:
> x <- matrix(1:1e6, 10)
> system.time( as.list(data.frame(x)) )
user system elapsed
1.24 0.00 1.22
> system.time( lapply(seq_len(ncol(x)), function(i) x[,i]) )
user system elapsed
0.2 0.0 0.2
发布于 2011-07-26 01:18:05
我相信data.frames是以列表的形式存储的。因此,强制似乎是最好的:
as.list(as.data.frame(x))
> as.list(as.data.frame(x))
$V1
[1] 1 2 3 4 5
$V2
[1] 6 7 8 9 10
基准测试结果很有趣。as.data.frame比data.frame更快,要么是因为data.frame必须创建一个全新的对象,要么是因为跟踪列名的成本很高(可以看看c(unname())与c()的比较)?@Tommy提供的lapply解决方案的速度要快一个数量级。通过手动强制可以在一定程度上改进as.data.frame()结果。
manual.coerce <- function(x) {
x <- as.data.frame(x)
class(x) <- "list"
x
}
library(microbenchmark)
x <- matrix(1:10,ncol=2)
microbenchmark(
tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i) ,
as.list(data.frame(x)),
as.list(as.data.frame(x)),
lapply(seq_len(ncol(x)), function(i) x[,i]),
c(unname(as.data.frame(x))),
c(data.frame(x)),
manual.coerce(x),
times=1000
)
expr min lq
1 as.list(as.data.frame(x)) 176221 183064
2 as.list(data.frame(x)) 444827 454237
3 c(data.frame(x)) 434562 443117
4 c(unname(as.data.frame(x))) 257487 266897
5 lapply(seq_len(ncol(x)), function(i) x[, i]) 28231 35929
6 manual.coerce(x) 160823 167667
7 tapply(x, rep(1:ncol(x), each = nrow(x)), function(i) i) 1020536 1036790
median uq max
1 186486 190763 2768193
2 460225 471346 2854592
3 449960 460226 2895653
4 271174 277162 2827218
5 36784 37640 1165105
6 171088 176221 457659
7 1052188 1080417 3939286
is.list(manual.coerce(x))
[1] TRUE
https://stackoverflow.com/questions/6819804
复制相似问题