2013-03-05 19 views
22

Jeśli mam kilka macierzy, które utworzyłem, jak mogę połączyć je w jedną tablicę? Mam 8 macierzy, z których każda ma 200 wierszy i 200 kolumn i muszę połączyć je w tablicę z dim = 200,200,8. Tak więc chcę, aby każda z moich matryc była fragmentem mojej tablicy.Łączenie macierzy w macierz w R

+0

robi wynik musi być tablicą 'tablica'? Czy 'list (x, y)' działa dla ciebie? – thelatemail

Odpowiedz

14

oto przykład dla dwóch osób. można łatwo rozszerzyć to do ośmiu

# create two matricies with however many rows and columns 
x <- matrix(1:9 , 3 , 3) 
y <- matrix(10:18 , 3 , 3) 
# look at your starting data 
x 
y 

# store both inside an array, with the same first two dimensions, 
# but now with a third dimension equal to the number of matricies 
# that you are combining 
z <- array(c(x , y) , dim = c(3 , 3 , 2)) 

# result 
z 
0

Jak o tym:

combmat <- array(dim=c(200,200,8), data=cbind(matrix1,matrix2,...,matrix8)) 
21

Można użyć funkcji abind z pakietu abind:

library(abind) 
newarray <- abind(mat1, mat2, mat3, mat4, along=3) 

## or if mats are in a list (a good idea) 

newarray <- abind(matlist, along=3) 
+3

Zdecydowanie droga, jako że 'abind' przejmuje od użytkownika wiele uciążliwych i podatnych na błędy indeksów księgowych. –

2

To zależy od tego, czy chcesz połącz je kolumnowo-major lub wiersz-major. Jest to analogiczne do użycia cbind i do łączenia wektorów w macierz. Ponieważ przechowuje R macierzy w celu kolumnowej duże, to najłatwiej zrealizować:

matrices <- list(
    matrix(1:9 , 3 , 3), 
    matrix(10:18 , 3 , 3) 
); 

#it is assumed all matrices in the list have equal dimensions 
array1 <- array(
    data = do.call(cbind, matrices), 
    dim = c(dim(matrices[[1]]), length(matrices)) 
); 

nowy wymiar (2, w tym przypadku) będzie 3. wymiaru. Sądząc po wyjściu metody druku, to wygląda dokładna, ponieważ dzieli drukiem przez ostatni wymiar:

> print(array1) 
, , 1 

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

, , 2 

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

Jednak czasami może być konieczne, aby połączyć je w pierwszym wymiarze, a nie, na przykład:

array2 <- array (
    data = do.call(rbind, lapply(matrices, as.vector)), 
    dim = c(length(matrices), dim(matrices[[1]])) 
); 

print(array2[1,,]) 

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

Na przykład, powiedz, że chcesz przypisać te macierze do ramki danych z kolumną; jedna matryca dla każdego rzędu. Wtedy pierwsze wymiary, a.k.a nrow trzeba dopasować w tablicy i danych ramki:

mydf <- data.frame(foo = 1:2, row.names=c("first", "second")) 
mydf$bar <- array1 
    Error in `$<-.data.frame`(`*tmp*`, "bar", value = 1:18) : 
    replacement has 3 rows, data has 2 

mydf$bar <- array2 
mydf$bar 
6

Oto wersja podobna do abind -ing, ale bez użycia żadnych dodatkowych pakietów. Zebrać wszystko do list a następnie użyj opcji sapply dydaktycznego do simplify= do "array" po nic nie robi dla każdej części listy (identity prostu zwraca obiekt i jest odpowiednikiem function(x) x):

sapply(list(x,y), identity, simplify="array") 
# similarly to save a couple of keystrokes, the following is usually identical 
sapply(list(x,y), I, simplify="array") 

#, , 1 
# 
#  [,1] [,2] [,3] 
#[1,] 1 4 7 
#[2,] 2 5 8 
#[3,] 3 6 9 
# 
#, , 2 
# 
#  [,1] [,2] [,3] 
#[1,] 10 13 16 
#[2,] 11 14 17 
#[3,] 12 15 18 

Jeśli chcesz aby zachować nazwy każdej oryginalnej matrycy w nowej tablicy jako identyfikatorów, spróbuj:

sapply(mget(c("x","y")), identity, simplify="array") 
+0

Funkcja aperm może być dalej używana do zmiany kolejności wymiarów tablic dla macierzy 3-D: new.mat <- aperm (old.mat, c (3, 1, 2)). W ten sposób new.mat [1 ,,] będzie odpowiadać macierzom [[1]]. –

0

Powiązane: How to stack multiple matrices in R

Problem ze wszystkimi rozwiązaniami do tej pory polega na tym, że gdy macierze (nie data.frame s - dla tego dplyr i data.table działają bez zarzutu) nie mają tej samej kolejności wierszy i kolumn, powiązanie będzie układać wartości względem siebie nawzajem, które nie są powiązane.

Jeśli chcesz sprawdzić i uwzględnić nazwy w każdym wymiarze, rzucić okiem na narray:

enter image description here

(disclaimer: Napisałem pakietu)

0
library('abind') 
abind(m1, m2, m3, along = 2.5) 
abind(m1, m2, m3, along = 3) 

m4 <- list(m1, m2, m3) 
abind(m4, along = 3) 

     along  input = matrix + matrix      output 
---------------------------------------------------------------------------- 
     0   split columns and row bind them     array 
     0.5  same as 0          array 
     1   combine matrices into one matrix by rowwise  matrix 
     1.5  split columns and column bind them    array 
     2   combine matrices into one matrix by columnwise matrix 
     2.5  Form an array with matrices      array 
     3   Same as 2.5          array