2013-05-14 11 views
8

में 2 डी मैट्रिक्स की सूची को ढेर करने का कार्यात्मक तरीका एक चालाक lapply के बाद, मुझे 2-आयामी मैट्रिक्स की एक सूची के साथ छोड़ दिया गया है।3 डी मैट्रिक्स

उदाहरण के लिए:

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]] 
... 

मैं चालू करने के लिए है कि एक 3-आयामी सरणी में करना चाहते हैं:

set.seed(1) 
replicate(5, matrix(runif(25),ncol=5))  

जाहिर है, अगर मैं दोहराने का उपयोग कर रहा मैं सिर्फ simplify चालू कर सकते हैं, लेकिन sapply परिणाम को सही ढंग से सरल नहीं करता है, और stack पूरी तरह से विफल रहता है। do.call(rbind,mylist) इसे 3 डी सरणी के बजाय 2 डी मैट्रिक्स में बदल देता है।

मैं इसे एक लूप के साथ कर सकता हूं, लेकिन मैं इसे संभालने के लिए एक साफ और कार्यात्मक तरीका ढूंढ रहा हूं।

निकटतम तरह से मैं के साथ आ गया है:

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

लेकिन मुझे लगता है कि जैसे असजीला है (क्योंकि यह disassembles और फिर वैक्टर की सरणी विशेषताओं reassembles, और बनाने के लिए परीक्षण का एक बहुत जरूरत सुरक्षित (जैसे कि प्रत्येक तत्व के आयाम एक ही हैं)।

+3

वहाँ abind पैकेज – baptiste

+2

मैं सहमत नहीं है कि आपके के सबसे करीबी रास्ता 'असजीला है और मैं आगे इससे सहमत नहीं है कि यह परीक्षण के "एक बहुत" की जरूरत है। यह स्पष्ट रूप से सही है और आपको 'do.call (c, test)' या 'असूची (परीक्षण)' की आवश्यकता है और उसके बाद इसकी पूरी तरह से सरल है। –

+0

@Dwin शायद मैं अपने कोड पर बहुत कठिन हूं। लेकिन वैक्टर/मैट्रिस के मूलभूत सिद्धांतों का लाभ लेना हमेशा मुझे परेशान करता है। प्वाइंट लिया गया, हालांकि, यह एक भयानक समाधान नहीं हो सकता है। –

उत्तर

6

आप abind पैकेज का उपयोग कर सकते हैं और उसके बाद का उपयोग do.call(abind, c(test, along = 3))

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

या आप पर sapply पर कॉल में उपयोग कर सकते हैं, (lapply के बजाय)। simplify = 'array', simplify = TRUE के समान नहीं है उस में simplify2array

जैसे तर्क higher परिवर्तन होगा, क्योंकि

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' के लिए पहला तर्क एक सूची हो सकता है, इसलिए आपको' do.call' की आवश्यकता नहीं है: 'testArray <- abind (test, along = 3) ' – cbeleites

+0

यह एक उत्तर चिह्नित कर रहा है क्योंकि यह दोनों' abind ' 'और', सरलीकृत = 'सरणी''। –

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

या आप की उम्मीद आकार समय से आगे पता नहीं है अगर:

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

आपका पिछला उत्तर अब मेरे अंदर शामिल किया गया है (आपका नया उत्तर बहुत साफ है) – mnel

+1

@mnel, धन्यवाद, मैंने वास्तव में 'सरलीकृत =' सरणी के उपयोग को हाल ही में 'sapply' पर प्रलेखन में देखा था और फिर देखा कि यह 'प्रतिलिपि' में भी था। लेकिन मैंने प्रतिलिपि का उपयोग करके * नहीं * के बारे में ओपी की टिप्पणी को गलत तरीके से पढ़ा था, इसलिए मैंने पुनः पढ़ने पर अपना पहला जवाब हटा दिया। –

+1

@ रिकार्डोस्पोर्टा 'सरलीकृत = "सरणी" वास्तव में मेरी समस्या को 10 में से 9 बार हल करेगी। धन्यवाद! –

2

एक सरणी बस एक परमाणु वीसी है आयाम के साथ टोर। test के प्रत्येक मैट्रिक्स घटक वास्तव में आयाम वाले एक वेक्टर भी हैं। इसलिए सबसे सरल समाधान मैं सोच सकता हूं कि वेक्टर में test सूची को अनलॉक करना है और इसे array और उपयुक्त रूप से आपूर्ति किए गए आयामों का उपयोग करके सरणी में परिवर्तित करना है।

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 

आप आयाम हार्डकोड नहीं करना चाहते हैं, तो हम कुछ मान्यताओं बनाने के लिए है, लेकिन आसानी से test से आयाम में भर सकते हैं, उदाहरण के लिए

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

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

मतलब यह है कि प्रत्येक घटक के आयाम सभी एक ही कर रहे हैं, लेकिन फिर मैं नहीं दिख रहा है कि कैसे आप एक 3-डी सरणी में उप मैट्रिक्स डाल सकता है कि अगर हालत नहीं रखता है।

यह सूची को अनलोल करने के लिए हैकी लग सकता है, लेकिन यह बस शोषण कर रहा है कि आर आयामों के साथ वैक्टर के रूप में मैट्रिस और सरणी को कैसे संभालता है।

+0

@ रिकार्डोस्पोर्टा हां का क्रमबद्ध करें। माफ़ कीजिये; मैंने 'सरणी' का उपयोग करके उत्तर की तलाश की और कोई भी नहीं देखा, और कुछ स्पष्टीकरण प्रदान करना चाहते हुए मैंने एक जवाब जोड़ा। ध्यान दें कि आपको पहले खंड में एक त्रुटि है - यह 'सी (मंद (परीक्षण [[1]]) होना चाहिए, 5)' –

+0

बिल्कुल पसीना नहीं है, और निश्चित रूप से, आपका उत्तर मेरे मुकाबले थोड़ा सा स्पष्टीकरण प्रदान करता है। पकड़ने के लिए धन्यवाद, मेरी गलती संपादित की गई –

+0

यदि कोई सूची की लंबाई से संबंधित सरणी के पहले आयाम को बनाने के लिए 3 डी सरणी को दोबारा बदलना चाहेगा, तो यह लाइन यह करेगी: testMat <- aperm (tmp2, c (3,1,2)) –

10

इस प्रयास करें:

simplify2array(test) 
+0

धन्यवाद, 'foreach' के परिणाम के साथ उपयोग करते समय यह मेरे लिए काम किया –

संबंधित मुद्दे