Uutta ja vanhaa korrespondenssianalyysista

[viesti Survo-keskustelupalstalla (2001-2013)]

Kirjoittaja: Kimmo Vehkalahti
Sähköposti:    -
Päiväys: 18.8.2005 20:23

Korrespondenssianalyysi (Correspondence Analysis, CA) on sekä
historiansa että tulostensa osalta värikäs menetelmä. Olen kertonut
siitä aiemmin monimuuttujamenetelmien monisteessani (Vehkalahti 2002,
40-48). Tässä jutussa keskityn enemmän menetelmän toteutustapoihin
Survossa. Olen laatinut uuden MCA-nimisen sukron, jolla menetelmän
soveltaminen sujuu vielä aiempaakin helpommin.


1.   Korrespondenssianalyysi Survossa ja muissa ohjelmissa

Korrespondenssianalyysilla tutkitaan ja kuvaillaan kahden muuttujan
välisiä (usein epälineaarisia) riippuvuuksia niiden keskinäisen
frekvenssitaulukon perusteella. Päätuloksena piirretään kuvia, joista
tehdään erilaisia päätelmiä. Kuviin voidaan liittää tietoja yhdestä
tai useammasta taustamuuttujasta (supplementary variable).

Survossa on jo pitkään ollut hyvät työkalut korrespondenssianalyysiin.
Perustan muodostaa CORRESP-moduli, jonka Seppo laati vuoden 1993
tietämillä. Korrespondenssianalyysi tuli myös mukaan omana lukunaan
Sepon monimuuttujamenetelmien oppikirjaan (Mustonen 1995). (Kirjan
päivitetty versio on julkaistu vuonna 2004 kokonaisuudessaan verkossa,
ks. http://www.survo.fi/monim/).

Menetelmälle ominaiset kaksoiskuvat (biplots) on ollut luontevaa tehdä
Survossa kerrostamalla kuvia yhteen. Tämä on onnistunut hyvin kaikkina
Survo-aikakausina (SURVO 84C, SURVO 98, SURVO MM) niin kuvaruudulla
(GPLOT) kuin PostScript-muodossa (PLOT). Korkeatasoinen grafiikka onkin
antanut selvän edun Survolle jos verrataan muihin ohjelmiin. Useissa
tilastollisissa ohjelmissa korrespondenssianalyysi on sen sijaan
loistanut poissaolollaan, ja vasta viime vuosina on alkanut tulla
esiin edes jollain lailla toimivia toteutuksia.

Survon työkalut ovatkin jatkuvasti olleet kilpailukykyisiä, jopa
helppokäyttöisempiä ja tuloksiltaan havainnollisempia kuin muiden
ohjelmien, esim. SPSS:n ja SAS:n. Nuo "suuret" ohjelmat ovat tämän
menetelmän osalta olleet varsin mitättömiä. Tämä ei ole vain oma
mielipiteeni, sillä olen kuullut samaa myös menetelmää soveltaneilta
tutkijoilta. Jotkut ovat siirtyneetkin Survon käyttöön turhauduttuaan
muiden ohjelmien korrespondenssianalyysitarjonnan heikkoon laatuun
(ks. esim. Siivonen & Wermundsen 2005).

Ilahduttavaa on, että R-ohjelmistossa on korrespondenssianalyysin
työkalut saatettu hyvälle mallille. Näitä mahdollisuuksiahan voivat
Survo-käyttäjätkin kokeilla mukavasti Sepon vastikään laatimalla
R-käyttöliittymällä. Aivan samaan palvelutasoon kuin Survossa ei
R:ssä kuitenkaan vielä näytetä yltävän.


2.   Moniulotteinen korrespondenssianalyysi Survossa

Survon CORRESP-moduli pohjautuu Lebartin, Morineaun ja Warwickin
(1984) kuvailevien monimuuttujamenetelmien kirjaan. Modulia
säestävät vuonna 1998 ohjelmoimani täydennyspalikat, joilla
hallitaan menetelmän yleistettyä muotoa, niin sanottua moniulotteista
korrespondenssianalyysia (Multiple Correspondence Analysis, MCA).
Myös sen teoriaperusteet on esitetty Lebartin ym. (1984) kirjassa.
Hyvä esitys löytyy myös mm. Gowerin ja Handin (1996) teoksesta.

Laskelmat tapahtuvat yleistetyssäkin muodossa CORRESP-modulilla,
mutta pohjana on yhden frekvenssitaulukon sijasta ns. Burtin taulu
(Burt 1950). Se on teknisesti luonnehdittuna symmetrinen
lohkolävistäjämatriisi, jonka lävistäjällä sijaitsevat kunkin
muuttujan frekvenssijakaumat lävistäjämatriiseina ja lävistäjän
ulkopuolella kaikkien muuttujien väliset parittaiset
frekvenssitaulukot. Burtin taulusta tunnetaan myös erilaisia
muunnelmia (ks. esim. Gower ja Hand 1996, 57-61).

Burtin taulu on siis keskeisessä osassa. Se muodostetaan joko
TAB-operaatiolla tehdystä moniulotteisesta, toimituskentässä
olevasta taulukosta tai suoraan havaintoaineistosta. Jälkimmäinen
tapa on useimmiten kätevämpi, eritoten kun luokittelijoiden ja/tai
luokkien määrä on suurempi. On huomattava, että moniulotteinen
taulukko on aidosti moniulotteinen, kun taas Burtin taulu koostuu
vain parittaisista kahden luokittelijan ristiintaulukoinneista.

Kun keväällä 1998 aloin laatia täydennyspalikoita, työskentelin
vaiheittain. Laadin alustavan ratkaisun vain sukrojen varaan
rajoittuen kentässä annettuihin taulukoihin. Muokkasin niitä
TAB-komennoilla ja sovelsin tuolloin uutta COMB-operaatiota
muodostaakseni binäärisen indikaattorimatriisin Z, josta Burtin
taulu syntyy kätevästi matriisikertolaskulla Z'Z. Sain aikaan
työkaluja eräitä todellisia tarpeita varten ja tein niillä tulosta
kesän aikana. Havaitsin kuitenkin, että tehoa tarvitaan lisää.
Burtin taulu oli voitava muodostaa suoraan Survo-datasta antamalla
vain luokittelutiedot samalla tavalla kuin TAB-operaatiossa.

Kesän lopussa (näihin aikoihin 7 vuotta sitten) ryhdyin "laiskasta
tyhmäksi" (ks. Mustonen 1996, 215) ohjelmoidakseni C-kielellä
BURT-nimisen modulin Survoon. Aloitin taulukoista jotta saatoin
vertailla tuloksia sukroilla tekemiini. Kun sain taulukko-osuuden
toimimaan, siirryin datan puolelle. Modulin dokumentaatiosta päätellen
homma alkoi toimia n. kolme viikkoa myöhemmin. En osaa sanoa miten
paljon nettoaikaa kulutin, mutta muistan viihtyneeni kyllä lähdekoodin
äärellä ajoittain hyvinkin intensiivisesti.

Lopputuloksena oli ehkäpä elegantein C-ohjelmani (samaa ei voi sanoa
työpöytäohjelmistani INDEX, DD, DM, TREE jne., jotka ovat syntyneet
vuosien aikana kerros kerrokselta). Modulin pääohjelma on kaikessa
yksinkertaisuudessaan seuraavanlainen:

  void main(int argc, char *argv[])
  {
      int i;
      s_init(argv[1]);
      if (g<3) { usage_info(); return; }
      i=spec_init(r1+r-1); if (i<0) return;
      i=check_params(); if (i<0) return;
      switch (source) {
          case TABLE: i=proceed_with_table(); if (i<0) return; break;
           case DATA: i=proceed_with_data(); if (i<0) return; break;
             default: usage_info(); return;
      }
      i=make_labels(); if (i<0) return;
      i=save_matrices(); if (i<0) return;
      s_end(argv[1]);
  }

Siis tarkistetaan parametrit, tehdään työt joko taulukon tai datan
pohjalta, rakennetaan otsikkotiedot ja talletetaan matriisit.

Moduli tallettaa Burtin taulun matriisitiedostoksi, jonka oletusnimi
on BURT.M. Onneksi Seppo oli Survon matriisiobjektien rakenteesta
päättäessään (jo ammoin n. 20 vuotta sitten!) sallinut rivi- ja
sarakeotsikoille (jotka jo sinällään ovat ainutlaatuinen ja hieno
konstruktio) tarvittaessa pidemmänkin nimen kuin datatiedoston
asettaman muuttujan kutsumanimen maksimipituus 8 merkkiä. Tämä on
aivan oleellinen yksityiskohta, sillä näin käyttäjän eri luokille
antamat nimet välittyvät lopullisiin kuviin asti automaattisesti
niin pitkinä kuin on tarpeen.

Toinen modulin tallettama matriisi on oletusnimeltään CLASS.M, ja se
sisältää eräitä tietoja luokittelijoista. Vuosien ajan CLASS.M oli
pelkkä vektori, joka kertoi kunkin luokittelijan luokkien lukumäärän.
Tieto on tarpeen tallettaa, sillä sen selvittäminen myöhemmin pelkän
Burtin taulun pohjalta olisi sukrolla turhan hankalaa.

Nyt tekemissäni uudistuksissa CLASS.M on saanut lisää vastuuta ja
laajentunut matriisiksi, jossa on kolme saraketta. Lisäsarakkeet
sisältävät tiedot muuttujien asteikkotyypeistä ja mahdollisista
taustamuuttujista. Nämä tiedot terävöittävät entisestään menetelmän
soveltamista Survossa.

Alkuperäinen vaiheittainen lähestymistapani on heijastunut myös
siihen, miten moniulotteista korrespondenssianalyysia on Survolla
käytännössä tehty. BURT-modulia ei ole yleensä käytetty suoraan,
vaan työt on tehty erilaisilla sukroilla kolmessa vaiheessa:

(1) Burtin taulun muodostaminen:

(1a) kentässä olevasta taulukosta:
      /BURT-TABLE <taulukko>,BURT.M,CLASS.M
tai
(1b) havaintoaineistosta (datatiedostosta):
      /BURT-DATA <aineisto>,BURT.M,CLASS.M

(2) Burtin taulun muokkaus uudeksi datatiedostoksi, johon
     tehdään myös tarvittavat tulosmuuttujat maskeineen:

      /BURT-MCORRESP <uusi_aineisto>,BURT.M,CLASS.M,dim
       Parametri dim kertoo, kuinka moneen dimensioon
        varaudutaan (oletus on 2).

(3) Moniulotteinen korrespondenssianalyysi:

      /MCORRESP <uusi_aineisto> 

Esimerkki menetelmän soveltamisvaiheista löytyy Survon kuvagallerian
sivulta http://www.survo.fi/galleria/047.html 

Alunperin en halunnut laittaa kaikkia vaiheita samaan, sillä näin
Burtin taululle muitakin käyttökohteita kuin tämän analyysin.
Toinen peruste oli se, että vaihe (2) oli aikoinaan erittäin raskas,
ja ellei luokitteluja ollut tarpeen muuttaa, oli huomattavasti
kevyempää toistaa analyysi aktivoimalla vain vaihe (3) uudelleen.
Tämä vaihe antaa käyttäjälle työkentän, jossa kuvaa voi tarkastella
ja säätää kaikkia yksityiskohtia. Myös kyseistä työkenttää olen
uusimmassa toteutuksessa kehittämässä monipuolisemmaksi.

Vuosien aikana olen käyttänyt tekemiäni työkaluja aktiivisesti sekä
tutkimuksessa että opetuksessa. Parhaillaan työstän artikkelia,
jossa analysoidaan Itämeren kalansaalisaineistoja 20 vuoden ajalta.
Ohjaan myös tilastotieteen gradua, jossa menetelmää sovelletaan
tapaturmia koskeviin rekisteriaineistoihin. Keväällä Lauri Tarkkosen
kanssa pitämämme monimuuttujamenetelmien kurssinkin yksi suosituimpia
aiheita tuntui olevan korrespondenssianalyysi; aivan samaan tapaan
kuin jo vuosina 1995-2001 monimuuttujamenetelmien aiheista pitämilläni
kursseilla Viikissä.

Olen saanut myös palautetta työkaluistani; mm. Petri Palmu on esittänyt
hyviä ehdotuksia joita olen yrittänyt ottaa huomioon nyt kun vihdoin
kaivoin toimituskentät esiin ja ryhdyin työhön. Onpahan taas hauska
seurata omia, vuosien takaisia työskentelyn jälkiä ja palauttaa mieliin
asioita ja ajatusprosesseja (vrt. Vehkalahti 2005)!


3.   Uusi suoraviivaisempi analyysisukro MCA

Kokemuksieni mukaan taulukoiden perusteella tehtävä analyysi (1a) on
hyödyksi enemmänkin opetuksessa kuin käytännön tutkimuksessa, jossa
pääpaino on ehdottomasti menetelmän soveltamisessa suoraan datasta (1b).
Koneet ovat nopeutuneet niin paljon sitten vuoden 1998, että vaihe (2)
sujuu kivutta vaikka sitä joutuisikin toistamaan. Olen silti tehnyt
myös joitakin nopeuttavia optimointeja kyseiseen vaiheeseen. Edelleen
kokemuksieni mukaan BURT-modulin tulosmatriisien nimiä ei juurikaan ole
tarpeen muutella, koska ne voi aina tehdä helposti uudelleen (vrt.
tulosmatriisit, PostScripttiedostot yms. Survossa muutenkin). Myös
uuden datan voi luoda ilman että käyttäjä keksii sille nimen (nimien
keksiminenhän on tunnetusti tietojenkäsittelyn vaikeimpia tehtäviä!).

Näin ollen olen päätynyt kokoamaan vaiheet (1)-(3) yhden sukron alle.
Sukron nimi on ytimekkäästi MCA, ja sitä kutsutaan yllätyksettömästi:

/MCA <aineisto> 

Sukro puolestaan kutsuu vuorollaan kaikkia kolmea em. sukroa ja jättää
lopuksi käyttäjälle työkentän aivan kuten aiemminkin. Täsmentävät
tiedot annetaan samalla tavalla kuin ennenkin, mutta eräiltä osin on
mukana uusia yksityiskohtia, joilla vaikutetaan suoraan sekä analyysiin
että sen lopputuloksena saataviin kuviin.

Muuttujat valitaan joko MASK:illa, VARS:illa tai FILE ACTIVATE:lla.
Useimmiten MASK on näistä kätevin. Analyysissa käytettävät muuttujat,
joiden perusteella koordinaatit lasketaan, aktivoidaan A-maskilla.
Uutuutena taustamuuttujat voidaan aktivoida jo tässä vaiheessa S:llä,
mikäli sellaisia on.


4.   Asteikkotiedot mukaan analyysiin

Uusi asia on myös, että muuttujille voi - ja kannattaa - laittaa
alkuperäiseen aineistoon mitta-asteikkotiedot (3. aktivointisarake,
tarkemmat ohjeet kyselyllä SCALES?). Tämähän on muutenkin erittäin
suositeltavaa. Survossa on mitta-asteikkojen hallinta viety (jo ajat
sitten) pidemmälle kuin missään tuntemassani ohjelmistossa, ja nyt
siitä otetaan hyöty irti myös korrespondenssianalyysissa.

BURT-modulin uusi versio tarkkailee siis mitta-asteikkotietoja. Sitä
kiinnostaa erityisesti mitkä muuttujista ovat nominaaliasteikollisia,
sillä niiden osalta ei kuvissa ole mielekästä yhdistää luokkien
pisteitä toisiinsa. Tähän asti pisteiden yhdistäminen on tehty kaikille
luokittelijoille Lebartin ym. (1984) hengessä, mutta oikoen mutkia
liiankin suoriksi nominaaliasteikollisten muuttujien osalta. Toisaalta
käyttäjä on voinut kohtuullisen helposti (vaihtamalla sopivasti
täsmennyksiä LINE=1 muotoon LINE=0) säätää lopputulosta sukron
tarjoamassa työkentässä. Muissa ohjelmissa en ole nähnyt minkäänlaista
automatiikkaa näiden viivojen piirtämiseen.

Nyt tämä tieto siis saadaan mukaan alusta asti (kunhan käyttäjä sen
dataansa asettaa, sillä mikään ohjelma ei voi automaattisesti tietää,
onko numeroilla 1,2,3,4 koodatun muuttujan luokilla tosiasiassa mitään
järjestysrelaatiota).

En voi olla mainitsematta, miten helppoa asteikkotietojen käsittely
(kuten moni muukin asia) on Survon C-ohjelmoijan näkökulmasta. Tässä
on pala BURT-modulin datankäsittelypuolen alkua:

    i=data_read_open(word[2],&dat); if (i<0) return -1;
    i=mask(&dat); if (i<0) return -1;
    scales(&dat);
    i=conditions(&dat); if (i<0) return -1;

Survon C-ohjelmakirjaston (ks. http://www.helsinki.fi/survo/c/lib.html)
valmiilla funktioilla saadaan hetkessä melkoisesti aikaan:

- avataan luettavaksi käyttäjän antama datatiedosto
- tutkitaan muuttujien aktivointitiedot, oli ne annettu sitten
  VARS- tai MASK-täsmennyksin tai FILE ACTIVATE:lla
- analysoidaan muuttujien asteikkotyypit ja jätetään turhat
  muuttujat (asteikkotietona '-') pois näkyvistä
- tutkitaan havaintojen rajaustiedot, oli ne annettu sitten
  IND-, CASES- tai SELECT-ehtoina tai näiden yhdistelminä
- kaikissa kohdissa varaudutaan virhetilanteisiin ja tarvittaessa
  ilmoitetaan käyttäjälle syntaksi- tms. virheestä

Täsmennykset on jo tätä ennen otettu haltuun em. pääohjelmassa
kirjastofunktiokutsulla

    i=spec_init(r1+r-1); if (i<0) return;

jossa r1 ja r ovat toimituskentän rivien sijaintiparametreja. Todella
yksinkertaista siis, jos C-ohjelmointi on tuttua. Ohjelmointitaitoa ei
tietenkään edellytetä Survon käyttäjiltä vaan ainoastaan niiltä "outoa
kaksoiselämää" viettäviltä, jotka tekevät ratkaisuja ja valintoja
"pinnan alla, alamaailmassa" (ks. Mustonen 1996, 218).

Lopulta BURT-modulin tarvitsee tietoja datasta kootessaan tarkistaa
vain scale_ok-nimisellä kirjastofunktiolla, onko muuttujan mittaustaso
vähintään järjestysasteikollinen:

    cscal[i] = (scale_ok(&dat,dat.v[i],ORDINAL_SCALE)) ? 1 : 0;

Jos on, talteen menee ykkönen. Muissa tapauksissa talletetaan
nominaaliasteikollisen muuttujan merkiksi nolla. Tieto kulkeutuu
lopuksi CLASS.M-matriisiin, josta sukrot saavat sen käyttöönsä.
Vaiheessa (2) sukro siirtää tiedon uuden datatiedoston muuttujien
asteikkomerkintöihin (todella näppärästi FILE MASK -operaation uusilla,
laajennetuilla muodoilla!), ja viimein vaiheessa (3) käyttää tietoa
kirjoittaen työkenttään LINE=0 tai LINE=1.


5.   Uuden MCA-sukron oletusarvojen säätäminen

Uskoisin että useimmissa tapauksissa analyysi sujuu tästä lähin
yksinkertaisesti antamalla tarvittavat luokittelut, aktivoimalla
vastaavat muuttujat ja kutsumalla MCA-sukroa ilman mitään muita
täsmennyksiä. Tarvittaessa oletusarvoja voi toki säätää, ja sitä
varten on tarjolla seuraavia täsmennyksiä:

/MCA <aineisto> 
     NEWDATA=<uusi_aineisto>      (oletus: _<aineisto>)
     DIM=<dim>                    (oletus: 2)
     BURT=<Burtin_taulu>          (oletus: BURT.M)
     CLASS=<luokittelijamatriisi> (oletus: CLASS.M)
     VARTYPE=<1,2,4,8>            (oletus: 2/4/1)

Näistä VARTYPE ansaitsee pienen lisäselityksen. Sillä hienosäädetään
frekvenssimuuttujien tyyppiä uudessa, analyysia varten vaiheessa (2)
tehtävässä aineistossa. Tähän asti tyyppi on ollut kiinteästi 2,
mutta on tullut vastaan tilanteita joissa se ei riitä (yksittäiset
frekvenssit kymmeniä tuhansia).

Nyt automatiikka nostaa tyypin 4:ään, jos se havaitsee vähintään
30000:n kokoisen alkion Burtin taulussa. Vastaavasti se pienentää
tyypin 1:een, mikäli maksimialkio on alle 200. Automatiikka ohitetaan
kokonaan, mikäli käyttäjä säätää tyypin haluamakseen
VARTYPE-täsmennyksellä. Tarkat tiedot muuttujatyypeistä ja rajoista
löytyvät kyselyllä FILE? kohdan 1 (General information) alta kohdasta
1 (Survo data files).


6.   Pohdintaa jatkokehityksestä

Uudistus on vielä sillä tavoin vaiheessa, että olen pohtinut myös uutta
täsmennystä, jolla voisi rajoittaa luotavien tulosmuuttujien määrää
uudessa aineistossa. Koordinaattimuuttujat ovat tietenkin aina tarpeen,
jotta kuvat saadaan piirrettyä, mutta erityisesti luokkakohtaiset
residuaalit sekä eräät yleistunnusluvut eivät läheskään aina kiinnosta
niin paljon. Residuaalien osalta on myös eräitä hieman auki olevia
kysymyksiä liittyen taustamuuttujiin. Vaihetta (2) nopeuttaisi, jos
turhat tulosmuuttujat voisi ohittaa.

Kesken on vielä myös työkentän monipuolistaminen. Olen ajatellut
dokumentoida sitä paremmin, jotta se olisi havainnollisempi ja helpompi
käyttäjän muokattavaksi. Julkaisuja varten joudutaan usein tyytymään
mustavalkoisiin kuviin, jolloin värien sijasta on eroteltava
luokittelijoiden tietoja esimerkiksi eri fonteilla ja/tai
viivatyypeillä. Näitä varten olen ajatellut tuottaa jotain valmista
pohjaa työkenttään.

Vielä yksi uudistus (joka on tosin vasta harkinnassa) koskee
havaintojen painottamista. BURT-modulissa voisi nimittäin ottaa
huomioon mahdollisen (esimerkiksi maskilla 'W' merkityn)
painomuuttujan, joka vaikuttaisi enemmän tai vähemmän frekvenssien
laskemiseen. Tämä on tullut vastaan tutkimusprojektissa, jossa toimin
gradun ohjaajana. Kyseisessä tapauksessa näyttäisi tosin siltä, ettei
painotuksella ole juuri mitään vaikutusta, mutta jossain muussa
tapauksessa voisi kenties ollakin.


7.   Lopuksi

Niille jotka ovat tänne asti kahlanneet, haluan vielä kertoa että uudet
työkalut ovat testausvaiheessa ja niitä voi kysellä suoraan minulta. Ne
tulevat aikanaan jakeluversioon, mutteivät ihan vielä. Uuden MCA-sukron
käyttö edellyttää SURVO MM:n versiota 2.25 (tai uudempaa), sillä olen
hyödyntänyt siinä FILE MASK -komennon uusia mahdollisuuksia.


Lähteet

Burt, Cyril (1950). The Factorial Analysis of Qualitative Data.
    Journal of Statistical Psychology, 3(3), 166-185.
Gower, J. C. & Hand, D. J. (1996). Biplots.
    Chapman & Hall.
Lebart, Ludovic & Morineau, A. & Warwick, K. M. (1984). Multivariate
    Descriptive Statistical Analysis. John Wiley & Sons.
Mustonen, Seppo (1995). Tilastolliset monimuuttujamenetelmät.
    Survo Systems. http://www.survo.fi/monim/ 
Mustonen, Seppo (1996). Survo ja minä.
    Survo Systems.
Siivonen, Yrjö & Wermundsen, Terhi (2005). Lepakoiden talvihorrospaikkojen
    vertailu. Monimuuttujamenetelmät-kurssin verkkoposteri.
    http://www.valt.helsinki.fi/blogs/momume/post14.htm 
Vehkalahti, Kimmo (2002). Monimuuttujamenetelmät.
    http://www.helsinki.fi/%7ekvehkala/mmm/moniste.pdf 
Vehkalahti, Kimmo (2005). Leaving useful traces when working with matrices.
    Research Letters in the Information and Mathematical Sciences, 8, 143-154.
    http://iims.massey.ac.nz/research/letters/volume8/vehkalahti/vehkalahti.pdf 

Vastaukset:
[ei vastauksia]

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!

Etusivu  |  Keskustelu
Copyright © Survo Systems 2001-2013. All rights reserved.
Updated 2013-06-15.