[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!