/ / Vykonajte operáciu na zoskupených stĺpcoch matice - r, matica

Vykonajte operáciu na zoskupených stĺpcoch matice - r, matice

Predpokladajme, že mám maticu M a vektor G celých čísel, také, že G má toľko položiek, koľko je stĺpcov v M. Napríklad (schematicky):

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

Vektor G kóduje zoskupenie Mstĺpce. Vo vyššie uvedenom príklade G kóduje tri skupiny stĺpcov, zodpovedajúce trom submaticiam uvedeným nižšie:

  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

(Pozn .: z dôvodu prehľadnosti som v tomto príklade vybral skupiny pozostávajúce zo susedných stĺpcov, ale všeobecne nemusí byť stĺpec v skupine súvislý. V takom prípade by usporiadanie skupín malo byť v poradí prvého objavenia sa v G.)

Chcem vykonať „kolaps“ (alebo"sumarizáciu") operácie na každom riadku každej z týchto submatíc a výsledné stĺpce zreťaziť do novej matice. Napríklad ak je kolabujúca operácia max, práve opísaný postup vygeneruje tri stĺpce zobrazené vpravo od šípky:

  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

Konečným výsledkom by teda bola matica:

 20   71   64
88   80   86
31   84   46
46   76   67

Ako sa dá robiť tento druh manipulácie v R?


(FWIW, nižšie je kód na vytvorenie M a G zobrazené vyššie.)

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)

odpovede:

4 pre odpoveď č. 1

Tu je jedna možnosť:

## 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

Funkcia function (x) sapply(split(x, 1:4), max) naozaj robí maximum riadkov.


3 pre odpoveď č. 2

Tu je ďalšia možnosť s 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

Alebo variácia vyššie uvedeného je

sapply(split(t(M), G), function(x) rowMaxs(matrix(x, nrow=4, byrow=TRUE)))

2 pre odpoveď č. 3

Ďalšia možnosť spoliehajúca sa na skutočnosť, že matice sa zvyčajne vypĺňajú podľa poradia stĺpcov:

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