2012-12-10 14 views
8

immagina di avere una matrice 3-dimensionale con righe, colonne e strati:Applicare una funzione a ciascuno strato di una matrice 3d, restituendo un array

A <- array (1:27, c(3,3,3)) 

e immaginare di avere una funzione che accetta una matrice come input e restituisce una matrice come output, come t.

Come si può applicare la funzione a ogni livello della matrice, restituendo un altro array delle stesse dimensioni come il primo?

mi sento come dovrebbe essere in grado di farlo con apply in qualche modo, ma non ci riesco.

Domanda bonus (sarei molto grato se avete risposto a questa domanda): è più veloce farlo, o fare una lista di ciascuna delle matrici dei livelli e la funzione lapply per loro?

-

Edit: si prega di non credo che tale questione venga risolta - la risposta qui sotto non risponde alla domanda.

risposta

4

si deve pensare che il margine (s) su cui si desidera estrarre i valori.

è possibile trasporre ciascuna delle 3rd matrici dimensione mediante l'applicazione di più di dimensioni 1 e 2 (righe e colonne per mancanza di una parola migliore)

apply(A,1:2,t) 
, , 1 

    [,1] [,2] [,3] 
[1,] 1 2 3 
[2,] 10 11 12 
[3,] 19 20 21 

, , 2 

    [,1] [,2] [,3] 
[1,] 4 5 6 
[2,] 13 14 15 
[3,] 22 23 24 

, , 3 

    [,1] [,2] [,3] 
[1,] 7 8 9 
[2,] 16 17 18 
[3,] 25 26 27 

È anche possibile utilizzare plyr e aaply che può agire in modo più intuitivo

library(plyr) 

aaply(A,3,t) 
, , = 1 


X1 1 2 3 
    1 1 4 7 
    2 10 13 16 
    3 19 22 25 

, , = 2 


X1 1 2 3 
    1 2 5 8 
    2 11 14 17 
    3 20 23 26 

, , = 3 


X1 1 2 3 
    1 3 6 9 
    2 12 15 18 
    3 21 24 27 

su quale sia più veloce lapply o apply, penserei forse lapply avrebbe vinto, ma si sarebbe comunque dovuto fare la riflessione su quali margini si desidera estrarre le matrici da.

solito trovo molto più facile pensare in una dimensione. Tutto sarebbe più semplice se la terra fosse piatta!

+0

Questo non è quello che intendevo. La risposta giusta dovrebbe avere il primo livello essere uguale a 't (matrice (1: 9, 3, 3))', che nessuno di questi è. –

+0

Questo è ciò che intendo dire dover riflettere attentamente sulle dimensioni per ottenere ciò che desideri. – mnel

+0

Nessuna delle possibili combinazioni dei margini dà la risposta che sto cercando, però. –

1

Un'altra possibilità per la trasposizione è funzione aperm.

A <- array (1:27, c(3,3,3)) 
# aperm permute the dimensions in the given order 
# here we want to permute dimension 1 and 2 
# so the new order is 2-1-3 instead of 1-2-3 
aperm(A, c(2,1,3)) 
    , , 1 

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

, , 2 

    [,1] [,2] [,3] 
[1,] 10 11 12 
[2,] 13 14 15 
[3,] 16 17 18 

, , 3 

    [,1] [,2] [,3] 
[1,] 19 20 21 
[2,] 22 23 24 
[3,] 25 26 27 

Per quanto riguarda l'applicazione di una funzione per ogni strato (dicono che si desidera moltiplicare ogni strato con un valore diverso) è interessato, ecco un'altra possibilità:

vec <- c(1,5,3) 
lapply(seq_along(vec), function(x)A[,,x]*vec[x]) 
[[1]] 
    [,1] [,2] [,3] 
[1,] 1 4 7 
[2,] 2 5 8 
[3,] 3 6 9 

[[2]] 
    [,1] [,2] [,3] 
[1,] 50 65 80 
[2,] 55 70 85 
[3,] 60 75 90 

[[3]] 
    [,1] [,2] [,3] 
[1,] 57 66 75 
[2,] 60 69 78 
[3,] 63 72 81 

Ma, come si vede crea un lista, quindi ha bisogno di un passo in più utilizzando la funzione simplify2array:

simplify2array(lapply(seq_along(vec),function(x)A[,,x]*vec[x])) 
, , 1 

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

, , 2 

    [,1] [,2] [,3] 
[1,] 50 65 80 
[2,] 55 70 85 
[3,] 60 75 90 

, , 3 

    [,1] [,2] [,3] 
[1,] 57 66 75 
[2,] 60 69 78 
[3,] 63 72 81 

O direttamente con sapply:

sapply(seq_along(vec), function(x)A[,,x]*vec[x], simplify="array") 
, , 1 

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

, , 2 

    [,1] [,2] [,3] 
[1,] 50 65 80 
[2,] 55 70 85 
[3,] 60 75 90 

, , 3 

    [,1] [,2] [,3] 
[1,] 57 66 75 
[2,] 60 69 78 
[3,] 63 72 81 
+1

Questo è bello. Stavo usando 't' arbitrariamente - ho un processo stocastico complesso che vorrei applicare alla matrice - ma è bello sapere che esiste' aperm'. :-) Anche le altre soluzioni sono belle, ma speravo di farlo in modo funzionale, ovvero passare i dati nella funzione apply piuttosto che far funzionare la funzione su dati al di fuori del suo ambito locale. –

+0

Intendi qualcosa come 'sapply (seq_along (vec), function (x, X) {X [,, x] * vec [x]}, simplify =" array ", X = A)'? – plannapus

Problemi correlati