[viesti Survo-keskustelupalstalla (2001-2013)]
| Kirjoittaja: | Kimmo Vehkalahti |
|---|---|
| Sähköposti: | - |
| Päiväys: | 16.2.2005 12:50 |
Valmistelen parhaillaan esitelmää kansainväliseen matriiseja ja
tilastotiedettä käsittelevään konferenssiin. Aiheena on jotakuinkin
"hyödyllisten jälkien jättäminen matriiseilla työskenneltäessä"
(hiven piilohauskaa matriisilaskennan perusteet tunteville: jälki
eli trace tarkoittaa myös neliömatriisin lävistäjäalkioiden summaa).
Yhtenä esitelmäni punaisena lankana toimivat matriisin rivi- ja
sarakeotsikot, jotka Survossa seuraavat eri matriisioperaatioita
loogisesti auttamalla oleellisesti työn dokumentoitumisessa ja/tai
dokumentoinnissa.
Seppo on puhunut tästä aiheesta usein, ja jopa saman konferenssin
vuoden 1999 kutsutussa esitelmässään, johon voi tutustua verkossa
osoitteessa http://www.helsinki.fi/survo/matrix99.html tai
Survossa valitsemalla alariviltä DEMO ja sitten MATRIX. Suomeksi
asiasta kertoo Survo ja minä -kirja (Mustonen 1996, 196-197).
Yhteinen käsityksemme on ollut, ettei missään muussa ohjelmistossa
ole mahdollisuutta samanlaiseen "otsikkoaritmetiikkaan" (SM) kuin
Survossa. Tätä käsitystä ovat vahvistaneet niin omat kuin muilta
tutkijoilta saamamme tiedot.
Päätin "varmistaa selustani" tutustumalla jälleen kerran itse eräisiin
muihin ohjelmistoihin (SPSS, SAS, R) juuri tämän asian kannalta.
Joidenkin mielestä asia saattaa vaikuttaa kaiken kaikkiaan pieneltä
tai peräti "akateemiselta", mutta mielestäni se ei sellainen ole.
Pienet asiat toistuvat jatkuvasti, ja vähänkään laajemmissa töissä
niiden merkitys vain korostuu. Ja onhan asia jo siltäkin kannalta
selvä, että tilastotieteessä on yleensä mitä luonnollisinta ajatella
havaintoMATRIISI-muotoista datan esitystä, jossa sekä havainnoilla
että muuttujilla on NIMET. Tätä kai voi pitää vähimmäisvaatimuksena,
jos puhutaan meta-data -käsitteestä. Kuitenkin yleisesti käytetyissä
matriisiohjelmissa (kuten Matlab) keskitytään vain numeeriseen dataan.
Esikuvana ovat tällöin pikemminkin matriisien matemaattiset esitykset,
eivät tilastolliset. Tilastotieteilijänä on vaikea hyväksyä pelkkien
numeroiden pyörittelyä; nimet ja muu sanallinen tieto ovat oleellinen
osa kokonaisuutta.
Huonosti käy edelleen ns. isoissa ohjelmissa (SPSS ja SAS). Tässä on
niillä työskentelystä pieni näyte, jonka olen ottanut James Stevensin
kirjasta Applied Multivariate Statistics for the Social Sciences:
SPSS:
MATRIX.
COMPUTE A = {2, 4, 1; 3, -2, 5}.
COMPUTE B = {1, 2; 2, 1; 3, 4}.
COMPUTE C = A*B.
COMPUTE E = {1, -1, 2; -1, 3, 1; 2, 1, 10}.
COMPUTE DETE = DET(E).
COMPUTE EINV = INV(E).
PRINT A.
PRINT B.
PRINT C.
PRINT E.
PRINT DETE.
PRINT EINV.
END MATRIX.
Kun nämä komennot suoritetaan Syntax-ikkunassa, saadaan
Output-ikkunaan seuraavaa:
Run MATRIX procedure:
A
2 4 1
3 -2 5
B
1 2
2 1
3 4
C
13 12
14 24
E
1 -1 2
-1 3 1
2 1 10
DETE
3
EINV
9.666666667 4.000000000 -2.333333333
4.000000000 2.000000000 -1.000000000
-2.333333333 -1.000000000 .666666667
------ END MATRIX -----
SAS:
proc iml;
a = {2 4 1, 3 -2 5};
b = {1 2, 2 1, 3 4};
c = a*b;
e = {1 -1 2, -1 3 1, 2 1 10};
dete = det(e);
einv = inv(e);
print a b c e dete einv;
Kun nämä komennot suoritetaan Program Editor -ikkunassa, saadaan
Output-ikkunaan seuraavaa:
A B C
2 4 1 1 2 13 12
3 -2 5 2 1 14 24
3 4
E DETE EINV
1 -1 2 3 9.6666667 4 -2.333333
-1 3 1 4 2 -1
2 1 10 -2.333333 -1 0.6666667
Samat temput Survolla näyttävät tällaiselta:
Survo:
MATRIX A ///
2 4 1
3 -2 5
MATRIX B ///
1 2
2 1
3 4
MAT SAVE A
MAT SAVE B
MAT C=A*B
MATRIX E ///
1 -1 2
-1 3 1
2 1 10
MAT SAVE E
MAT DETE=DET(E)
MAT EINV=INV(E)
Otetaan näin määritellyt ja lasketut matriisit näkyville
toimituskenttään:
MAT LOAD A END+2
MAT LOAD B END+2
MAT LOAD C END+2
MAT LOAD E END+2
MAT LOAD DETE END+2
MAT LOAD EINV END+2
MATRIX A
/// 1 2 3
1 2 4 1
2 3 -2 5
MATRIX B
/// 1 2
1 1 2
2 2 1
3 3 4
MATRIX C
A*B
/// 1 2
1 13 12
2 14 24
MATRIX E
/// 1 2 3
1 1 -1 2
2 -1 3 1
3 2 1 10
MATRIX DETE
DET(E)
/// det
det 3
MATRIX EINV
INV(E)
/// 1 2 3
1 9.66667 4.00000 -2.33333
2 4.00000 2.00000 -1.00000
3 -2.33333 -1.00000 0.66667
Erona edellisiin ovat paitsi matriisin ns. sisäinen nimi, joka kertoo
sen syntyhistoriasta, niin myös rivi- ja sarakeotsikot.
Oletuksena käytetään otsikoita 1, 2, ..., mutta ne kannattaa usein
korvata paremmin kuvaavilla, esimerkiksi näin:
MAT RLABELS AR TO A
MAT CLABELS AS TO A
MAT RLABELS BR TO B
MAT CLABELS BS TO B
MAT RLABELS ER TO E
MAT CLABELS ES TO E
Tällöin, kun toistetaan em. operaatiot
MAT C=A*B
MAT DETE=DET(E)
MAT EINV=INV(E)
matriisit näyttävät seuraavilta:
MAT LOAD A END+2
MAT LOAD B END+2
MAT LOAD C END+2
MAT LOAD E END+2
MAT LOAD DETE END+2
MAT LOAD EINV END+2
MATRIX A
/// AS1 AS2 AS3
AR1 2 4 1
AR2 3 -2 5
MATRIX B
/// BS1 BS2
BR1 1 2
BR2 2 1
BR3 3 4
MATRIX C
A*B
/// BS1 BS2
AR1 13 12
AR2 14 24
MATRIX E
/// ES1 ES2 ES3
ER1 1 -1 2
ER2 -1 3 1
ER3 2 1 10
MATRIX DETE
DET(E)
/// det
det 3
MATRIX EINV
INV(E)
/// ER1 ER2 ER3
ES1 9.66667 4.00000 -2.33333
ES2 4.00000 2.00000 -1.00000
ES3 -2.33333 -1.00000 0.66667
Huomaa miten otsikot seuraavat operaatioita automaattisesti:
matriisi C perii otsikot matriiseilta A ja B matriisikertolaskun
(skalaaritulo) sääntöjen mukaisesti (A:n rivit, B:n sarakkeet)
käänteismatriisissa EINV myös otsikot vaihtavat paikkaa
determinanttimatriisi (1x1) saa otsikoikseen "det"; näin siihen
voidaan viitata myös editoriaalisen aritmetiikan lausekkeissa
Tein samat asiat vielä kertaalleen R-ohjelmistolla:
R:
A <- matrix(c(2, 4, 1, 3, -2, 5), 2, 3, TRUE)
B <- matrix(c(1, 2, 2, 1, 3, 4), 3, 2, TRUE)
C <- A %*% B
E <- matrix(c(1, -1, 2, -1, 3, 1, 2, 1, 10), 3, 3)
dete <- det(E)
library(nlme)
einv <- solve(E)
Kun nämä komennot suoritetaan komentoikkunassa ja otetaan saadut
objektit näkyviin, saadaan seuraavaa:
> A
[,1] [,2] [,3]
[1,] 2 4 1
[2,] 3 -2 5
> B
[,1] [,2]
[1,] 1 2
[2,] 2 1
[3,] 3 4
> C
[,1] [,2]
[1,] 13 12
[2,] 14 24
> E
[,1] [,2] [,3]
[1,] 1 -1 2
[2,] -1 3 1
[3,] 2 1 10
> dete
[1] 3
> einv
[,1] [,2] [,3]
[1,] 9.666667 4 -2.3333333
[2,] 4.000000 2 -1.0000000
[3,] -2.333333 -1 0.6666667
>
Otsikoille siis on paikat. Voisiko niitä käyttää fiksumminkin?
Pengoin helppejä jonkin aikaa, ja havaitsin, että R:ssä voidaan
jonkin verran hallita matriisien rivi- ja sarakeotsikoita, joskaan
ei missään tapauksessa Survon matriisitulkin veroisesti.
Asetetaan otsikot vastaavasti kuin Survossa:
rownames(A) <- rownames(A, FALSE, "AR")
colnames(A) <- colnames(A, FALSE, "AS")
rownames(B) <- rownames(B, FALSE, "BR")
colnames(B) <- colnames(B, FALSE, "BS")
rownames(E) <- rownames(E, FALSE, "ER")
colnames(E) <- colnames(E, FALSE, "ES")
Tällöin, kun toistetaan em. operaatiot
C <- A %*% B
dete <- det(E)
einv <- solve(E)
matriisit näyttävät seuraavilta:
> C
BS1 BS2
AR1 13 12
AR2 14 24
> as.matrix(dete)
[,1]
[1,] 3
> einv
ER1 ER2 ER3
ES1 9.666667 4 -2.3333333
ES2 4.000000 2 -1.0000000
ES3 -2.333333 -1 0.6666667
Otsikkoajattelu ei ole viety yhtä pitkälle kuin Survossa, mikä näkyy
esim. dete-nimisessä objektissa. Se on oletuksena skalaari, mutta
otettu tässä näkyviin matriisityyppisenä. Otsikoille ei kuitenkaan
ole keksitty käyttöä vaan ne ovat numeeriset.
Vähänkään pidemmälle menevissä operaatioissa otsikot eivät myöskään
seuraa lainkaan mukana, vaikka käänteismatriisissa ne vielä pysyvätkin
(ja vaihtavat loogisesti paikkojaan - seikka josta Seppo voisi kertoa
lukuisia tarinoita...). Otan esimerkin singulaariarvohajotelmasta:
(Vertailun vuoksi lähdetään tekstitiedostossa annetusta datasta.)
Survo:
Siirretään data tekstitiedostosta Survo-dataksi:
FILE SAVE KYMMEN.TXT TO KYMMEN / DELIMITER=TAB
Valitaan muuttujat (urheilijan nimi ja 10 lajipistemuuttujaa):
MASK=A-AAAAAAAAAA--
Siirretään data matriisiksi X:
MAT SAVE DATA KYMMEN TO X
Matriisissa X on tällöin riviotsikkoina urheilijoiden nimet ja
sarakeotsikkoina muuttujien nimet (tässä X:n vasen yläkulma):
MAT LOAD X(1:5,1:5)
MATRIX X
/// 100m Pituush Kuula Korkeus 400m
Skowrone 853 931 725 857 838
Hedmark 853 853 814 769 833
Le_Roy 879 951 799 779 838
Zeilbaue 826 931 793 865 875
Zigert 879 840 924 857 788
Korrelaatiomatriisi keskistyksen ja normeerauksen kautta:
MAT R=MTM(NRM(CENTER(X)))
MAT LOAD R(1:5,1:5)
MATRIX R
NRM(CENTER(X))'*NRM(CENTER(X))
/// 100m Pituush Kuula Korkeus 400m
100m 1.00000 0.17199 -0.02795 -0.41170 0.45608
Pituush 0.17199 1.00000 -0.03439 -0.00332 0.13346
Kuula -0.02795 -0.03439 1.00000 0.16254 -0.30371
Korkeus -0.41170 -0.00332 0.16254 1.00000 -0.33883
400m 0.45608 0.13346 -0.30371 -0.33883 1.00000
Korrelaatiomatriisin singulaariarvohajotelma; 3 tulosmatriisia:
MAT SVD OF R TO U,D,V
MAT LOAD U(100m:Kuula,svd1:svd3)
MATRIX U
Usvd(NRM(CENTER(X))'*NRM(CENTER(X)))
/// svd1 svd2 svd3
100m -0.14219 0.57768 -0.15266
Pituush 0.01217 0.31832 0.64953
Kuula 0.48489 0.14380 -0.24312
MAT LOAD D
MATRIX D
Dsvd(NRM(CENTER(X))'*NRM(CENTER(X)))
/// sing.val
svd1 2.602056
svd2 2.007813
svd3 1.206620
svd4 1.067052
svd5 0.931538
svd6 0.594690
svd7 0.569080
svd8 0.538683
svd9 0.244855
svd10 0.237613
MAT LOAD V(100m:Kuula,svd1:svd3)
MATRIX V
Vsvd(NRM(CENTER(X))'*NRM(CENTER(X)))
/// svd1 svd2 svd3
100m -0.14219 0.57768 -0.15266
Pituush 0.01217 0.31832 0.64953
Kuula 0.48489 0.14380 -0.24312
Kaikkiin matriiseihin tulee siis automaattisesti loogiset otsikot
(ja sen lisäksi em. sisäinen nimi).
R:
Siirretään data tekstitiedostosta R-dataksi:
> kymmen <- read.table("kymmen.txt", header=TRUE, row.names=1)
Siirretään valitut muuttujat datasta matriisiksi X:
> X <- as.matrix(kymmen[,2:11])
Matriisissa X on tällöin riviotsikkoina urheilijoiden nimet ja
sarakeotsikkoina muuttujien nimet (tässä X:n vasen yläkulma):
> X[1:5,1:5]
X100m Pituush Kuula Korkeus X400m
Skowrone 853 931 725 857 838
Hedmark 853 853 814 769 833
Le_Roy 879 951 799 779 838
Zeilbaue 826 931 793 865 875
Zigert 879 840 924 857 788
Korrelaatiomatriisi keskistyksen ja normeerauksen kautta:
> n <- dim(X)[1]
> M <- scale(X, center=TRUE, scale=TRUE) * sqrt(1/(n-1))
> R <- t(M) %*% M
> R[1:5,1:5]
X100m Pituush Kuula Korkeus X400m
X100m 1.0000000 0.171985363 -0.02795230 -0.411699539 0.4560816
Pituush 0.1719854 1.000000000 -0.03439298 -0.003324598 0.1334633
Kuula -0.0279523 -0.034392979 1.00000000 0.162541961 -0.3037074
Korkeus -0.4116995 -0.003324598 0.16254196 1.000000000 -0.3388272
X400m 0.4560816 0.133463323 -0.30370738 -0.338827204 1.0000000
Korrelaatiomatriisin singulaariarvohajotelma; 3 tulosmatriisia:
> sing <- svd(R)
> names(sing)
[1] "d" "u" "v"
> sing$u
[,1] [,2] [,3] ...
[1,] -0.14219133 0.57767851 0.152659096
[2,] 0.01216543 0.31832234 -0.649528313
[3,] 0.48488958 0.14379809 0.243121420
...
> sing$d
[1] 2.6020563 2.0078135 1.2066202 1.0670519 0.9315382 0.5946902 0.5690795
[8] 0.5386829 0.2448548 0.2376125
> sing$v
[,1] [,2] [,3] ...
[1,] -0.14219133 0.57767851 0.152659096
[2,] 0.01216543 0.31832234 -0.649528313
[3,] 0.48488958 0.14379809 0.243121420
...
Otsikoita ei siis R:ssä ole ulotettu kaikkialle, vaikka periaatteessa
(ja osittain myös käytännössä) niitä onkin mahdollista hallita. En ole
kuullut tai nähnyt kenenkään niitä R:ssä hyödyntävän, eikä tavallaan
ihme: vaadittiinhan tässäkin jo datan sisäänlukuvaiheessa käyttäjän
aktiivisempi panos asiaan (optio "row.names" read.table-funktiossa).
(Survossa tätä vastaa nimimuuttujan aktivointi MASK-komennossa.)
Voin nähdäkseni hyvin jatkaa esitykseni valmistelua tältä pohjalta.
Myös matriisien kanssa työskentelyssä Survo on käyttöliittymänsä
puolesta ollut jo aikoja sitten aikaansa edellä, kuten R:n alulle
laittanut Robert Gentleman myös totesi Tampereella viime syksynä
pitämänsä esitelmän alkajaisiksi.
- Kimmo
| Vastaukset: |
|---|
Survo-keskustelupalstan (2001-2013) viestit arkistoitiin aika ajoin sukrolla, joka automaattisesti rakensi viesteistä (yli 1600 kpl) HTML-muotoisen sivukokonaisuuden. Vuoden 2013 alusta Survo-keskustelua on jatkettu entistäkin aktiivisemmin osoitteessa forum.survo.fi. Tervetuloa mukaan!