Suponha que eu tenha uma matriz M
e vetor G
de inteiros, tais que G
tem tantas entradas quantas as colunas M
. Por exemplo (esquematicamente):
G: 1 1 1 2 2 3 3 3 3
M: 4 20 12 4 71 46 45 25 64
50 54 88 1 80 8 86 71 26
28 7 31 44 84 46 35 32 0
45 15 46 76 39 67 10 59 59
O vetor G
codifica um agrupamento de M
"s colunas. No exemplo acima, G
codifica os três grupos de colunas, correspondentes às três submatrizes mostradas abaixo:
4 20 12
50 54 88
28 7 31
45 15 46
4 71
1 80
44 84
76 39
46 45 25 64
8 86 71 26
46 35 32 0
67 10 59 59
(NB: Por uma questão de clareza, neste exemplo eu escolhi grupos consistindo de colunas contíguas, mas em geral, as colunas em um grupo não precisam ser contíguas. Neste caso, a ordenação dos grupos deve ser a ordem da primeira aparição em G
.)
Eu quero executar um "colapso" (ou"resumindo") a operação em cada linha de cada uma dessas submatrizes e concatene as colunas resultantes em uma nova matriz. Por exemplo, se a operação de recolhimento for max
, o procedimento que acabamos de descrever geraria as três colunas mostradas abaixo à direita da seta:
4 20 12 20
50 54 88 -> 88
28 7 31 31
45 15 46 46
4 71 71
1 80 -> 80
44 84 84
76 39 76
46 45 25 64 64
8 86 71 26 -> 86
46 35 32 0 46
67 10 59 59 67
O resultado final seria, portanto, a matriz:
20 71 64
88 80 86
31 84 46
46 76 67
Como se faz esse tipo de manipulação em R?
(FWIW, abaixo é o código para criar o M
e G
Mostrado acima.)
G <- c(1, 1, 1, 2, 2, 3, 3, 3, 3)
M <- matrix(c( 4, 20, 12, 4, 71, 46, 45, 25, 64,
50, 54, 88, 1, 80, 8, 86, 71, 26,
28, 7, 31, 44, 84, 46, 35, 32, 0,
45, 15, 46, 76, 39, 67, 10, 59, 59),
nrow = 4,
byrow = TRUE)
Respostas:
4 para resposta № 1Aqui está uma possibilidade:
## I know your matrix has 4 rows, that is what the `4` in the following means
lst <- split(M, rep(G, each = 4L))
sapply(lst, function (x) sapply(split(x, 1:4), max) )
# 1 2 3
#1 20 71 64
#2 88 80 86
#3 31 84 46
#4 46 76 67
A função function (x) sapply(split(x, 1:4), max)
está realmente fazendo fila máxima.
3 para resposta № 2
Aqui está outra opção com rowMaxs
library(matrixStats)
sapply(split.default(as.data.frame(M), G), function(x) rowMaxs(as.matrix(x)))
# 1 2 3
#[1,] 20 71 64
#[2,] 88 80 86
#[3,] 31 84 46
#[4,] 46 76 67
Ou uma variação do acima é
sapply(split(t(M), G), function(x) rowMaxs(matrix(x, nrow=4, byrow=TRUE)))
2 para resposta № 3
Outra possibilidade, confiando no fato de que as matrizes são normalmente preenchidas por ordem de coluna:
simplify2array(by(t(M), G, function(x) sapply(x,max) ))
# 1 2 3
#V1 20 71 64
#V2 88 80 86
#V3 31 84 46
#V4 46 76 67