2013-05-14 14 views
8

Zeki lapply'dan sonra, 2 boyutlu matrislerin bir listesiyle kaldım. Örneğin2d matrislerinin listesini 3B matrisine yığmak için işlevsel yol

:

set.seed(1) 
test <- replicate(5, matrix(runif(25),ncol=5), simplify=FALSE) 
> test 
[[1]] 
      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 0.8357088 0.29589546 0.9994045 0.2862853 0.6973738 
[2,] 0.2377494 0.14704832 0.0348748 0.7377974 0.6414624 
[3,] 0.3539861 0.70399206 0.3383913 0.8340543 0.6439229 
[4,] 0.8568854 0.10380669 0.9150638 0.3142708 0.9778534 
[5,] 0.8537634 0.03372777 0.6172353 0.4925665 0.4147353 

[[2]] 
      [,1]  [,2]  [,3]  [,4]  [,5] 
[1,] 0.1194048 0.9833502 0.9674695 0.6687715 0.1928159 
[2,] 0.5260297 0.3883191 0.5150718 0.4189159 0.8967387 
[3,] 0.2250734 0.2292448 0.1630703 0.3233450 0.3081196 
[4,] 0.4864118 0.6232975 0.6219023 0.8352553 0.3633005 
[5,] 0.3702148 0.1365402 0.9859542 0.1438170 0.7839465 

[[3]] 
... 
Ben 3 boyutlu bir dizi içine çevirmek istiyorum

: Ben çoğaltmak kullanıyorsam

Açıkçası
set.seed(1) 
replicate(5, matrix(runif(25),ncol=5))  

, sadece simplify açabilirsiniz, ancak sapply sonucu düzgün şekilde basitleştirmez ve stack tamamen başarısız olur. do.call(rbind,mylist), 3B diziden ziyade 2d matrisine dönüştürür.

Bunu bir döngü ile yapabilirim, ancak bunun üstesinden gelmek için düzgün ve işlevsel bir yol arıyorum.

array(do.call(c, test), dim=c(dim(test[[1]]),length(test))) 

Fakat bu ayrıştırır, çünkü (inelegant var ve sonra vektörlerin dizisi özelliklerini reassembles ve yapmaya test çok ihtiyacı var gibi hissediyorum:

ben ile geldim yakın yoludur kasa (her bir elemanın boyutları aynı olduğu gibi).

+3

Ben senin 'en yakın yolu' inelegant ve ben daha da o test "çok şey" ihtiyacı olduğunu katılmıyorum katılmıyorum abind paket – baptiste

+2

var. Açıkça doğru ve "do.call (c, test)" veya "unlist (test)" e ihtiyacınız var ve bundan sonra tamamen basit. –

+0

@Dwin belki kendi kodumda çok zorum. Ancak vektörlerin/matrislerin temellerinden faydalanmak beni her zaman tedirgin ediyor. Ancak, alınan nokta korkunç bir çözüm olmayabilir. –

cevap

6

için abind paketini kullanmak ve daha sonra kullanabilir do.call(abind, c(test, along = 3))

library(abind) 
testArray <- do.call(abind, c(test, along = 3)) 

Veya simplify = 'array''u sapply numaralı çağrıya (lapply yerine) kullanabilirsiniz. simplify = 'array' o simplify2array

eg argüman higher değişecek gibi simplify = TRUE aynı değildir

foo <- function(x) matrix(1:10, ncol = 5) 
# the default is simplify = TRUE 
sapply(1:5, foo) 
     [,1] [,2] [,3] [,4] [,5] 
[1,] 1 1 1 1 1 
[2,] 2 2 2 2 2 
[3,] 3 3 3 3 3 
[4,] 4 4 4 4 4 
[5,] 5 5 5 5 5 
[6,] 6 6 6 6 6 
[7,] 7 7 7 7 7 
[8,] 8 8 8 8 8 
[9,] 9 9 9 9 9 
[10,] 10 10 10 10 10 
# which is *not* what you want 
# so set `simplify = 'array' 
sapply(1:5, foo, simplify = 'array') 
, , 1 

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

, , 2 

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

, , 3 

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

, , 4 

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

, , 5 

    [,1] [,2] [,3] [,4] [,5] 
[1,] 1 3 5 7 9 
[2,] 2 4 6 8 10 
+1

"Abind" in ilk argümanı bir liste olabilir, bu yüzden "do.call" 'a ihtiyaç duymazsınız: 'testArray <- abind (test, boyunca = 3)' – cbeleites

+0

Her ikisine de isabet ettiği için bu cevabı işaretlemek 've', basitleştirin = 'dizi'. –

2
test2 <- unlist(test) 
dim(test2) <- c(dim(test[[1]]),5) 

veya vaktinden beklenen boyutunu bilmiyorsanız:

dim3 <- c(dim(test[[1]]), length(test2)/prod(dim(test[[1]]))) 
dim(test2) <- dim3 
+0

Önceki cevabınız artık benimsenmiştir (yeni cevabınız gayet temizdir) – mnel

+1

@mnel, teşekkürler, sadece 'sadeliğini kullanmanın' basitçe farkına vardım '' '' '' aynı zamanda 'Replicate' idi. Ancak OP'nin Replicate kullanarak * not * ile ilgili yorumunu yanlış okumuştum, dolayısıyla yeniden okuma üzerine ilk cevabımı sildim. –

+1

@RicardoSaporta 'simplify =" array "' aslında 10'dan 9 defa problemimi çözebilir. Teşekkürler! –

2

Bir dizi sadece bir atomik vec'dir boyutları ile tor. test'un matris bileşenlerinin her biri, yalnızca boyutlarına sahip bir vektördür. Bu yüzden düşünebildiğim en basit çözüm, test listesini bir vektöre açıp array ve uygun şekilde sağlanan boyutları kullanarak bir diziye dönüştürmektir.

set.seed(1) 
foo <- replicate(5, matrix(runif(25),ncol=5)) 
tmp <- array(unlist(test), dim = c(5,5,5)) 

> all.equal(foo, tmp) 
[1] TRUE 
> is.array(tmp) 
[1] TRUE 
> dim(tmp) 
[1] 5 5 5 

Eğer boyutları kodlamalısınız istemiyorsanız, biz örneğin bazı varsayımlar yapmak zorunda ama kolayca test dan boyutta doldurabilirsiniz

tmp2 <- array(unlist(test), dim = c(dim(test[[1]]), length(test))) 

> all.equal(foo, tmp2) 
[1] TRUE 

Bu, her bileşenin boyutları aynı olduğunu varsayar, ama sonra bu koşul tutmaz eğer bir 3 boyutlu diziye alt matrisleri koymak nasıl görmüyorum.

Bu, listeyi açmak için hacky görünebilir, ancak bu basitçe R'nin matrisleri ve dizileri boyutlarıyla vektörler olarak nasıl işlediğini kullanmaktır.

+0

@RicardoSaporta Evet sayısı. Afedersiniz; 'Array' kullanarak Cevapları aradım ve hiç görmedim ve bir açıklama ekledim, bir açıklama ekledim. İlk öbekte bir hata olduğunu unutmayın - c (loş (test [[1]]), 5) ' –

+0

hiç ter olmamalıdır ve kesinlikle cevabınız benimkinden daha iyi bir açıklama sunar. Yakalama için teşekkürler, benim hata düzenledim –

+0

Eğer dizinin birinci boyutu listenin uzunluğuna karşılık gelen yapmak için 3d dizi yeniden şekillendirmek istiyorsanız, bu satır bunu yapar: testMat <- aperm (tmp2, c (3,1,2)) –

10

bu deneyin:

simplify2array(test) 
+0

Teşekkürler, 'foreach' sonucu ile çalışırken benim için çalıştı –

İlgili konular