Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何将矩阵转换为R中的列向量列表?_List_R_Matrix - Fatal编程技术网

List 如何将矩阵转换为R中的列向量列表?

List 如何将矩阵转换为R中的列向量列表?,list,r,matrix,List,R,Matrix,假设要将矩阵转换为列表,其中列表的每个元素都包含一列list()或as.list()显然不起作用,直到现在,我使用了一个hack,使用tapply的行为: x <- matrix(1:10,ncol=2) tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i) )将数据帧转换为列表似乎可行: > as.list(data.frame(x)) $X1 [1] 1 2 3 4 5 $X2 [1] 6 7 8 9 10 >

假设要将矩阵转换为列表,其中列表的每个元素都包含一列
list()
as.list()
显然不起作用,直到现在,我使用了一个hack,使用
tapply
的行为:

x <- matrix(1:10,ncol=2)

tapply(x,rep(1:ncol(x),each=nrow(x)),function(i)i)

)

将数据帧转换为列表似乎可行:

> as.list(data.frame(x))
$X1
[1] 1 2 3 4 5

$X2
[1]  6  7  8  9 10
> str(as.list(data.frame(x)))
List of 2
 $ X1: int [1:5] 1 2 3 4 5
 $ X2: int [1:5] 6 7 8 9 10

我相信数据帧是以列表的形式存储的。因此,强制似乎是最好的:

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
manual.concure在我的发现下:

作为一个有效的解决方案,在my R v2.13.0安装中,这看起来还可以:

> y <- c(unname(as.data.frame(x)))
> y
[[1]]
[1] 1 2 3 4 5

[[2]]
[1]  6  7  8  9 10
>y
[[1]]
[1] 1 2 3 4 5
[[2]]
[1]  6  7  8  9 10

不能说任何关于性能比较或它有多干净;-)

加文的回答简单而优雅。但如果有许多列,则更快的解决方案是:

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 
>x系统时间(作为列表(数据帧(x)))
用户系统运行时间
1.24    0.00    1.22 
>系统时间(lappy(seq_len(ncol(x)),函数(i)x[,i]))
用户系统运行时间
0.2     0.0     0.2 

为了给猫剥皮,将数组视为向量,就像它没有dim属性一样:

 split(x, rep(1:ncol(x), each = nrow(x)))

使用
plyr
对于以下情况非常有用:

library("plyr")

alply(x,2)

$`1`
[1] 1 2 3 4 5

$`2`
[1]  6  7  8  9 10

attr(,"class")
[1] "split" "list" 

我知道这在R中是一种诅咒,我并没有太多的声誉来支持这一点,但我发现for循环更有效。我使用以下函数将matrix mat转换为其列列表:

mat2list <- function(mat)
{
    list_length <- ncol(mat)
    out_list <- vector("list", list_length)
    for(i in 1:list_length) out_list[[i]] <- mat[,i]
    out_list
}

mat2list您可以使用
apply
,然后使用
c
do.call

x <- matrix(1:10,ncol=2)
do.call(c, apply(x, 2, list))
#[[1]]
#[1] 1 2 3 4 5
#
#[[2]]
#[1]  6  7  8  9 10

x在列数较小且恒定的普通情况下,我发现最快的选择是简单地硬编码转换:

mat2list  <- function (mat) lapply(1:2, function (i) mat[, i])
mat2list2 <- function (mat) list(mat[, 1], mat[, 2])


## Microbenchmark results; unit: microseconds
#          expr   min    lq    mean median    uq    max neval
##  mat2list(x) 7.464 7.932 8.77091  8.398 8.864 29.390   100
## mat2list2(x) 1.400 1.867 2.48702  2.333 2.333 27.525   100

mat2listconvertRowsToList{BBmisc}

将data.frame或矩阵的行(列)转换为列表

BBmisc::convertColsToList(x)
参考:

新功能将在v3.6中以R为基础。在此之前,本着与@mdsumner的回答类似的精神,我们也可以这样做

split(x, slice.index(x, MARGIN))
根据
asplit()
的文档。然而,如前所示,所有基于
split()
的解决方案都比@Tommy的
lappy/`[`
慢得多。这也适用于新的
asplit()
,至少在其当前形式下是如此

split_1 <- function(x) asplit(x, 2L)
split_2 <- function(x) split(x, rep(seq_len(ncol(x)), each = nrow(x)))
split_3 <- function(x) split(x, col(x))
split_4 <- function(x) split(x, slice.index(x, 2L))
split_5 <- function(x) lapply(seq_len(ncol(x)), function(i) x[, i])

dat <- matrix(rnorm(n = 1e6), ncol = 100)

#> Unit: milliseconds
#>          expr       min        lq     mean   median        uq        max neval
#>  split_1(dat) 16.250842 17.271092 20.26428 18.18286 20.185513  55.851237   100
#>  split_2(dat) 52.975819 54.600901 60.94911 56.05520 60.249629 105.791117   100
#>  split_3(dat) 32.793112 33.665121 40.98491 34.97580 39.409883  74.406772   100
#>  split_4(dat) 37.998140 39.669480 46.85295 40.82559 45.342010  80.830705   100
#>  split_5(dat)  2.622944  2.841834  3.47998  2.88914  4.422262   8.286883   100

dat <- matrix(rnorm(n = 1e6), ncol = 1e5)

#> Unit: milliseconds
#>          expr       min       lq     mean   median       uq      max neval
#>  split_1(dat) 204.69803 231.3023 261.6907 246.4927 289.5218 413.5386   100
#>  split_2(dat) 229.38132 235.3153 253.3027 242.0433 259.2280 339.0016   100
#>  split_3(dat) 208.29162 216.5506 234.2354 221.7152 235.3539 342.5918   100
#>  split_4(dat) 214.43064 221.9247 240.7921 231.0895 246.2457 323.3709   100
#>  split_5(dat)  89.83764 105.8272 127.1187 114.3563 143.8771 209.0670   100
split_1 split_4(dat)37.998140 39.669480 46.85295 40.82559 45.342010 80.830705 100
#>split_5(dat)2.622944 2.841834 3.47998 2.88914 4.422262 8.286883 100
数据单位:毫秒
#>expr最小lq平均uq最大neval
#>split_1(dat)204.69803 231.3023 261.6907 246.4927 289.5218 413.5386 100
#>分割2(dat)229.38132 235.3153 253.3027 242.0433 259.2280 339.0016 100
#>拆分_3(dat)208.29162 216.5506 234.2354 221.7152 235.3539 342.5918 100
#>分割4(dat)214.43064 221.9247 240.7921 231.0895 246.2457 323.3709 100
#>分割5(dat)89.83764 105.8272 127.1187 114.3563 143.8771 209.0670 100

在tidyverse的
purrr
包中有一个函数
array\u tree()
,它可以以最小的麻烦完成此操作:

x <- matrix(1:10,ncol=2)
xlist <- purrr::array_tree(x, margin=2)
xlist

#> [[1]]
#> [1] 1 2 3 4 5
#>  
#> [[2]]
#> [1]  6  7  8  9 10

(这是我对一个类似问题的答案的逐字复制)

使用
asplit
将矩阵转换为向量列表

asplit(x, 1) # split into list of row vectors
asplit(x, 2) # split into list of column vectors

创建以矩阵矩阵矩阵的列作为其元素的列表的最简单方法是使用R中的data.frame对象在内部表示为列列表这一事实。因此,所需的一切 下面是一行吗

mat.list <- as.data.frame(mat)

mat.list被加文打败了5秒。该死,“你是人类”屏幕?:-)抽签的运气好吧,我想,@Joris溜到我前面回答Perter Flom的问题后我才看到这个。另外,
as.data.frame()
松开了数据框的名称,所以
data.frame()
稍微好一点。相当于
手动强制(x)
可以
取消类(as.data.frame(x))
。谢谢Marek。这大约快了6%,大概是因为我可以避免使用函数定义/调用。有趣。我认为这也可以通过强制来实现。
c(as.data.frame(x))
产生与
as.list(as.data.frame(x)相同的行为
我认为是这样的,因为样本列表/矩阵的成员属于同一类型,但我不是专家。这是
tapply
所做的核心。但它更简单:)。可能较慢但好看的解决方案将是
split(x,col(x))
(和
split(x,row(x))
。我检查了它。同样快的将是
split(x,c(col(x)))
。但它看起来更糟。split(x,col(x))看起来更好-隐式强制到向量是好的…经过大量测试后,这似乎工作得最快,特别是对于很多行或列。请注意,如果
x
有列名,那么
split(x,col(x,as.factor=TRUE))
将保留名称。我想知道优化的Rccp解决方案是否可以更快。+1关于各种解决方案的相对效率,这是迄今为止最好的答案。但我认为为了获得相同的结果,您需要执行lappy(seq_len(nrow(x)),函数(I)x[I,])然后是较慢的。当然这会删除列名,但它们在原始问题中似乎并不重要。Tommy的解决方案更快、更紧凑:
system.time(lappy(seq_len(ncol(x)),function(i)x[,i]))用户:1.668系统:0.016运行时间:1.693试图在不同的上下文中解决此问题,无效:……查找此项:
vec2=castmarixtosequenceoflists(vecs);
unlist(apply(x,2,list),recursive=FALSE)
split_1 <- function(x) asplit(x, 2L)
split_2 <- function(x) split(x, rep(seq_len(ncol(x)), each = nrow(x)))
split_3 <- function(x) split(x, col(x))
split_4 <- function(x) split(x, slice.index(x, 2L))
split_5 <- function(x) lapply(seq_len(ncol(x)), function(i) x[, i])

dat <- matrix(rnorm(n = 1e6), ncol = 100)

#> Unit: milliseconds
#>          expr       min        lq     mean   median        uq        max neval
#>  split_1(dat) 16.250842 17.271092 20.26428 18.18286 20.185513  55.851237   100
#>  split_2(dat) 52.975819 54.600901 60.94911 56.05520 60.249629 105.791117   100
#>  split_3(dat) 32.793112 33.665121 40.98491 34.97580 39.409883  74.406772   100
#>  split_4(dat) 37.998140 39.669480 46.85295 40.82559 45.342010  80.830705   100
#>  split_5(dat)  2.622944  2.841834  3.47998  2.88914  4.422262   8.286883   100

dat <- matrix(rnorm(n = 1e6), ncol = 1e5)

#> Unit: milliseconds
#>          expr       min       lq     mean   median       uq      max neval
#>  split_1(dat) 204.69803 231.3023 261.6907 246.4927 289.5218 413.5386   100
#>  split_2(dat) 229.38132 235.3153 253.3027 242.0433 259.2280 339.0016   100
#>  split_3(dat) 208.29162 216.5506 234.2354 221.7152 235.3539 342.5918   100
#>  split_4(dat) 214.43064 221.9247 240.7921 231.0895 246.2457 323.3709   100
#>  split_5(dat)  89.83764 105.8272 127.1187 114.3563 143.8771 209.0670   100
x <- matrix(1:10,ncol=2)
xlist <- purrr::array_tree(x, margin=2)
xlist

#> [[1]]
#> [1] 1 2 3 4 5
#>  
#> [[2]]
#> [1]  6  7  8  9 10
x <- matrix(1:10,ncol=2)
colnames(x) <- letters[1:2]
xlist <- purrr::array_tree(x, margin=2)
xlist

#> $a
#> [1] 1 2 3 4 5
#>
#> $b
#> [1]  6  7  8  9 10
asplit(x, 1) # split into list of row vectors
asplit(x, 2) # split into list of column vectors
mat.list <- as.data.frame(mat)