2016-06-19 24 views
9

Voglio dividere matrici di dimensioni k x l in blocchi di dimensioni n x n considerando un OFSET o (come la funzione di Mathematica Partition fa).Split una matrice in blocchi di dimensione n con compensato i (metodo vectorized)

Ad esempio, data una matrice A come

A <- matrix(seq(1:16), nrow = 4, ncol = 4) 

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

e dimensione del blocco = 3, offset = 1, voglio come output i quattro sottomatrici che otterrebbe da

A[1:3, 1:3] 
A[1:3, 2:4] 
A[2:4, 1:3] 
A[2:4, 2:4] 

Se l'offset erano pari a 2 o 3, l'uscita di questo esempio dovrebbe essere solo la sottomatrice che mi da

A[1:3, 1:3] 

Come posso vettorializzare questo?

+0

Si potrebbe indice negativo, anche se questo può essere specifico caso: 'applicare (combn (c (-1, -1, -4, -4), 2), 2, function (x) {list (A [x [1], x [2]])}) – alistaire

+0

Cosa dovremmo avere se ' offset == 2'? – Psidom

+0

@Psidom, un offset di 2 righe e 2 colonne. Nella matrice 4 x 4 dell'esempio precedente gli offset 2 e 3 forniscono entrambi la sottomatrice 'A [1: 3, 1: 3]' – andandandand

risposta

3

Potrebbe esserci un modo più elegante. Ecco come farei scrivendo una funzione myPartition che simula la funzione mathematica Partition. Innanzitutto utilizzare Map per creare l'indice possibile lungo l'asse di riga e colonna in cui si utilizza seq per prendere offset e quindi utilizzare cross2 da purrr per creare un elenco di tutte le combinazioni possibili dell'indice di sottoinsiemi. Infine utilizzare lapply per sottoporre a subset la matrice e restituire un elenco di matrice di sottoinsiemi;

I risultati dei test su compensato 1, 2 e 3 sono i seguenti, che sembra comportarsi come previsto:

library(purrr) 
ind <- function(k, n, o) Map(`:`, seq(1, k-n+1, by = o), seq(n, k, by = o)) 

# this is a little helper function that generates subset index according to dimension of the 
# matrix, the first sequence construct the starting point of the subset index with an interval 
# of o which is the offset while the second sequence construct the ending point of the subset index 
# use Map to construct vector from start to end which in OP's case will be 1:3 and 2:4. 

myPartition <- function(mat, n, o) { 
    lapply(cross2(ind(nrow(mat),n,o), ind(ncol(mat),n,o)), function(i) mat[i[[1]], i[[2]]]) 
} 

# This is basically an lapply. we use cross2 to construct combinations of all subset index 
# which will be 1:3 and 1:3, 1:3 and 2:4, 2:4 and 1:3 and 2:4 and 2:4 in OP's case. Use lapply 
# to loop through the index and subset. 

# Testing case for offset = 1 
myPartition(A, 3, 1) 

# [[1]] 
#  [,1] [,2] [,3] 
# [1,] 1 5 9 
# [2,] 2 6 10 
# [3,] 3 7 11 

# [[2]] 
#  [,1] [,2] [,3] 
# [1,] 2 6 10 
# [2,] 3 7 11 
# [3,] 4 8 12 

# [[3]] 
#  [,1] [,2] [,3] 
# [1,] 5 9 13 
# [2,] 6 10 14 
# [3,] 7 11 15 

# [[4]] 
#  [,1] [,2] [,3] 
# [1,] 6 10 14 
# [2,] 7 11 15 
# [3,] 8 12 16 

# Testing case for offset = 2 
myPartition(A, 3, 2) 
# [[1]] 
#  [,1] [,2] [,3] 
# [1,] 1 5 9 
# [2,] 2 6 10 
# [3,] 3 7 11 

# Testing case for offset = 3 
myPartition(A, 3, 3) 
# [[1]] 
#  [,1] [,2] [,3] 
# [1,] 1 5 9 
# [2,] 2 6 10 
# [3,] 3 7 11 
2

ne dite di questo utilizzando base R, l'idea è di generare tutte le possibili finestre (cioè winds) di dimensioni n*n mentre si tiene conto dello offset. Quindi stampare tutte le possibili permutazioni degli elementi di winds nella matrice A (ad esempio perms). Funziona con qualsiasi A della dimensione k*l.

A <- matrix(seq(1:16), nrow = 4, ncol = 4) 
c <- ncol(A); r <- nrow(A) 
offset <- 1; size <- 3 
sq <- seq(1, max(r,c), offset) 
winds <- t(sapply(sq, function(x) c(x,(x+size-1)))) 
winds <- winds[winds[,2]<=max(r, c),] # check the range 
if (is.vector(winds)) dim(winds) <- c(1,2) # vector to matrix 
perms <- expand.grid(list(1:nrow(winds), 1:nrow(winds))) 
out=apply(perms, 1, function(x) { 
    a11 <- winds[x[1],1];a12 <- winds[x[1],2];a21 <- winds[x[2],1];a22 <- winds[x[2],2] 
    if (ifelse(r<c, a12<=r, a22<=c)) { # check the range 
     cat("A[", a11, ":", a12, ", ", a21, ":", a22, "]", sep="", "\n") 
     print(A[a11:a12, a21:a22]) 
    } 
}) 

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

Per size=3 e offset=2 o offset=3:

# A[1:3, 1:3] 
    # [,1] [,2] [,3] 
# [1,] 1 5 9 
# [2,] 2 6 10 
# [3,] 3 7 11 

Per offset=2 e size=2:

# A[1:2, 1:2] 
    # [,1] [,2] 
# [1,] 1 5 
# [2,] 2 6 
# A[3:4, 1:2] 
    # [,1] [,2] 
# [1,] 3 7 
# [2,] 4 8 
# A[1:2, 3:4] 
    # [,1] [,2] 
# [1,] 9 13 
# [2,] 10 14 
# A[3:4, 3:4] 
    # [,1] [,2] 
# [1,] 11 15 
# [2,] 12 16 
Problemi correlati