Tapahtumadatojen muokkausta elinaikadatoiksi / VAR, FILE AGGR, FILE

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

Tapahtumadatojen muokkausta elinaikadatoiksi / VAR, FILE AGGR, FILE

Petri Palmu

Ohessa on vuoden 2018 tilastoseminaarin (laiva) esitystä, jossa jumppasin pitkittäisaineistoa sellaiseen muotoon, josta voisi tehdä kestoanalyyseja.  

Alla on toimituskenttä kontrollisarakkeineen (tuon voi kopsata suoraan Survoon/Survo R:ään ja vetäistä vaikka /ACTIVATE + läpi.  

*
* Tekaistu leikkidata, jossa
* ajassa havainnoidaan joukkoa yksilöitä.
*
* Ongelma/tavoite: muokata dataa elinaika-analyyseihin tms.
* Saada ohjelma toimimaan erilaisissa tilanteissa.
*
*Esitys Survo-laivaseminaarissa 2018
*Esityksen B-osa (Survolla "hapuilua").
*Liittyy elinaikadatojen esikäsittelyyn.
*
*Alla on tehty leikkidata prosessi-/episodijaksojen
*tilastolliseen analyysiin. Dataa kertyy jostain prosessista
*(esim. palvelutapahtumat, työttömyysrekisteri,...).
*Tietoina on
* ID = yksilö, T = Aika, U = tapahtuma (esim. työttömyys, lääkitys)
* X = "muu" muuttuja (taustatieto)
*
*Tässä varsinainen tilamuuttuja on U, tilat eivät välttättä
*ole toisensa poissulkevia. Lisäksi eri systeemeistä voi
*tulla osin päällekäistä informaatiota (samasta asiasta).
*Ajatus on luoda vähän hankalampi data ja miettiä mitä
*eri ulottuvuuksia/ongelmia datankäsittelyyn aiheutuu :)
*
*Analyyseissa mallinnetaan mahdollisesti useiden prosessien
*kestojen välisiä yhteyksiä. Esim. työllistämistoimintaan
*altistumisen kesto/määrä -> työllistymisnopeus.
*
*Käytännössä ongelmana voi olla, että havainnointiin liittyy "sensurointia",
*mahdollisesti sekä alku- että loppupäähän. Tietyssä mielessä
*loppupää on lienee melkein jonkin relaation suhteen sensuroitu
*(ellei kyseessä ole ihan lopullinen tapahtuma, kuten kuolema).
*Alkupäässä ongelma on, ettei esim. tiedetä koska työttömyys- tai
*jokin palvelujakso alkoi (tai esim. kuinka pitkään jo asunut tietyssä
*kunnassa).
*
*DATA _K
*ID  T   U   X
*1   1   0   1
*1   2   0   1
*1   3   0   0
*1   4   1   0
*1   5   1   0
*1   6   0   1
*1   7   0   1
*1   8   1   0
*1   9   1   0
*1   10  0   0
*1   11  1   1
*2   3   1   0
*2   4   1   0
*2   5   0   0
*2   6   1   1
*2   7   1   1
*2   8   1   0
*2   7   1   1
*2   8   1   0
*2   9   1   0
*2   10  0   0
*2   11  0   1
*2   6   0   1
*2   7   0   1
*3   8   1   0
*4   1   0   1
*4   2   0   0
*4   3   1   0
*4   4   1   0
*4   5   1   0
*4   6   1   1
*4   7   1   0
*4   8   1   0
*5   4   1   0
*12  6   0   1
*12  7   0   1
*12  8   0   1
*12  9   0   1
*12  10  0   0
*12  11  0   0
*2   1   3   1
*2   5   3   0
*2   6   3   1
*2   7   3   1
*_  -    -   -
*
*
*Viimeisellä riillä ID:stä tehdään merkkijono (voi olla esim. hetu tv).
*Aikamuuttuja on numeerinen, koska tarkoitus on laskea ajallisia
*etäisyyksiä, kestoja.
*REPLACE "dTUNIT" "Tdistance"
*FILE SHOW K0
*............................
*
* Määritellään maksimiaikaetäisyys, joka punoo
* "tippuvat" tapahtumat toisiinsa (saman tilan episodiksi).
*SAVEP CUR+1,CUR+1,dtcrit  / !!!!!
*  Tdistance=1 / Maksimiaikaväli, joka sitoo tapahtuman yhdeksi episodiksi
*
*
* Tdistance esim. 1 päivä, 1 viikko, 1 kk,...
* Jos Tdistance'a kasvattaa, niin etäämmälläkin toisistaan
* olevat tapahtumat sidotaan samaksi prosessiksi.
*
*FILE SHOW K0
*
*/ACTIVATE2 +
*
+TUTSAVE F2ESC.TUT / Tekee saman kuin näppäinyhdistelmä F2 + Esc
{init}{tempo -2}{R}
{pre}{act}{end}
*
*/F2ESC
+FILE COPY _K TO NEW K00 / Datan lukeminine .SVOksi
*
*..........................
* Poistetaan viimeinen "ohjausrivi" (normaalisti
*  string muodostetaan jo aiemmassa vaiheessa esim. hetu).
*
+FILE COPY K00 TO NEW K0 / IND=T,!MISSING
*..............................
*
*
+FILE UPDATE K0
* Copy of data matrix _K
*FIELDS: (active)
*   1 SA_   2 ID       (##)  Tutkimusyksilö ID string-muuttuja
*   2 NA_   1 T        (##)  Mittausjankohta
*   3 NA_   1 U        (#)   Tapahtuma/prosessitila (0/1)
*   4 NA_   1 X        (#)   Taustamuuttuja
*END
*
*
*.........................
*
+/F2ESC
*FILE SORT K0 BY ID,U,T TO K1 / järjestetään data oikein
*FILE EXPAND K1,5,500 / varataan lisää tilaa muuttujille
*VAR ORD1=ORDER TO K1   / Havaintojen raakajärjestys
*
*.......................................
*FILE SHOW K1
*
+#LOADP dtcrit,CUR+1 / Tulostetetaan Tdistance
*  Tdistance=1 / Maksimiaikaväli, joka sitoo tapahtuman yhdeksi episodiksi
*##################
*
* Vaihe: "change points"
*     ID,T,U
*     U0=0 / Mikä oletus U:lle?
*     C1=if(str(ID,1)=str(ID[-1],1))then(0)else(1)
*
+/F2ESC
*VAR dID:1=if(ORDER=1)then(1)else(C1) TO K1 / ID:n vaihtumispiste
*VAR dIDU:1=if(ORDER=1)then(U0)else(min(1,(1-dID)*(abs(U-U[-1])))) TO K1 / U:n vaihtuminen
*VAR dIDT:2=if(ORDER=1)then(0)else((1-dIDU)*(1-dID)*(abs(T-T[-1]))) TO K1 /
*
*FILE SHOW K1
*.................................
+TIME Thu May 17 08:19:55 2018
*FILE SHOW K2
* ACT_BREAK =1
*.......................
*  Järjestetään ID U ja T
+FILE SORT K1 BY ID,U,T  TO K2
*........................
*......................
*  Lasketaan:
*
*  CT = Tapahtuman/prosessin kesto
*  T1 =
*
+#LOADP dtcrit,CUR+1
*  Tdistance=1 / Maksimiaikaväli, joka sitoo tapahtuman yhdeksi episodiksi
*############
*
*FILE SHOW K2
*  A1=if(dIDT>Tdistance)then(0)else(1)
*  A2=if(CT[+1]=0)then(min(1,CT))else(0)
*  C1=if(str(ID,1)=
*
+/F2ESC
*VAR APU:1=if(ORDER=1)then(1)else(A1) TO K2
*VAR CT=0 TO K2 / Cumulative time
*VAR CT=if(ORDER=1)then(0)else(APU*(1-dID)*(1-dIDU)*(dIDT+CT[-1])) TO K2
*VAR VIKA=if(CT[+1]=0)then(1)else(0) TO K2
*
*Vanha
*VAR VIKA2=if(ORDER=1)then(min(1,abs(ID-ID[+1])*abs(U-U[+1])))else(A2) TO K2 / Jakson viimeinen
*
* JaksoID
*
+/F2ESC
*VAR JID=if(CT=0)then(1)else(0) TO K2
*VAR JID=if(ORDER>1)then(B1)else(JID) TO K2
*
* B1=JID+JID[-1]
*
*...............................
*FILE SHOW K2
*
+#STAT K2,CUR+1 / VARS=ORD1 RESULTS=0
*Basic statistics: K2 N=44
*Variable: ORD1     ~ORDER
*min=1        in obs.#1 (1)
*max=44       in obs.#44 (5)
*mean=22.5     stddev=12.84523 skewness=0        kurtosis=-1.242121
*autocorrelation=1.0000
*lower_Q=11.5     median=22.5     upper_Q=33.5
*##################
*   Viimeisen havainnon käsittely
*
+VAR VIKA=if(ORDER=max)then(1)else(VIKA) TO K2
*
*...................................
*FILE SHOW K2
*FILE SHOW K3
* Sitten dataa "tiivistetään" ottamalla vain
* episodien alku- ja lopputapahtumat mukaan.
*
* C1=CT,0 C3=VIKA,0  C2=VIKA,1
*
+FILE COPY K2 TO NEW K3 / SELECT=C2+(C1*C3)
*
*..........................
*
*TIME Thu May 10 16:03:14 2018
*  ACT_BREAK=1
*.....................
*FILE SHOW K3
*/ACTIVATE2 +
*.......................
*  Aggregoidaan jokainen ID-episodi
*
+FILE DEL TMP1
+FILE DEL K4
+FILE SORT K3 BY JID TO TMP1
+FILE AGGR TMP1 BY JID TO K4
*VARIABLES:
*JID FIRST JID
*ID  FIRST ID
*U   FIRST U           / 0,1
*MT0   MIN   T     / abs alkuaika
*MT1   MAX   T
*T0  MIN   CT     / rel alkuaika
*T1  MAX   CT
*mX MEAN X
*N N T
*END
*.........................
*
*FILE SHOW K4
*FILE SHOW K5
+FILE SORT K4 BY ID,MT0 TO K5
*
*....................
*   Sensuroidut havainnot (välisensurointi?)
*     Mittausjärjestelmän (msys) alku ja loppu
*    msyst0=1 msyst1=11
+/F2ESC
*VAR LHID:1=if(MT0>msyst0)then(1)else(0) TO K5  / alusta sensuroitu (left)
*VAR RHID:1=if(MT1<msyst1)then(1)else(0) TO K5  / lopusta sensuroitu (right)
*
*Ongelma:
*Tässä pitää katsoa laajemmin ID:n koko historiaa, nyt sensuroinnit
*tapahtuvat episodi-indeksi (JID) tasolla. Voidaan tehdä FILE
*AGGR + FILE COPY (MATCH) avulla, mutta voi olla suurilla datoilla
*liian hidas. Kenties parempi tehdä tietokannassa, jonne tämän
*käsittelyn datat tultaneen viemään.
*
*
*GOTO CUR-200
*.......................
+#STAT K4,CUR+1 / RESULTS=20 VARS=JID,T1
*Basic statistics: K4 N=17
*Variable: JID
*min=1        in obs.#1
*max=17       in obs.#17
*mean=9        stddev=5.049752 skewness=0        kurtosis=-1.313725
*autocorrelation=1.0000
*lower_Q=4.75     median=9        upper_Q=13.25
*
*Variable: T1
*min=0        in obs.#3
*max=5        in obs.#7
*mean=1.470588 stddev=1.585782 skewness=1.182138 kurtosis=0.357655
*lower_Q=0        median=1        upper_Q=2
*#####################
*...............................
*
+TIME Thu May 17 08:19:57 2018
*
* ACT_BREAK=1   / tämä vaatii /ACTIVATE2 sukron, ks. tämän postauksen lopussa
*
*..............................
*RESIZE 55,100
*FILE SHOW K5
*  Esikäsitelty data
*
*#FILE LOAD +K5,CUR+1 / NAMES8=1
*JID      ID       U        MT0      MT1      T0       T1       mX       N        LHID     RHID
*       1.000 1    0   1   3       0.000       2.000       0.500      2   0   1
*       4.000 1    1   4   5       0.000       1.000       0.000      2   1   1
*       2.000 1    0   6   7       0.000       1.000       1.000      2   1   1
*       5.000 1    1   8   9       0.000       1.000       0.000      2   1   1
*       3.000 1    0  10  10       0.000       0.000       0.000      1   1   1
*       6.000 1    1  11  11       0.000       0.000       1.000      1   1   0
*       7.000 12   0   6  11       0.000       5.000       0.500      2   1   0
*      12.000 2    3   1   1       0.000       0.000       1.000      1   0   1
*      10.000 2    1   3   4       0.000       1.000       0.000      2   1   1
*       8.000 2    0   5   7       0.000       2.000       0.500      2   1   1
*      13.000 2    3   5   7       0.000       2.000       0.500      2   1   1
*      11.000 2    1   6   9       0.000       3.000       0.500      2   1   1
*       9.000 2    0  10  11       0.000       1.000       0.500      2   1   0
*      14.000 3    1   8   8       0.000       0.000       0.000      1   1   1
*      15.000 4    0   1   2       0.000       1.000       0.500      2   0   1
*      16.000 4    1   3   8       0.000       5.000       0.000      2   1   1
*      17.000 5    1   4   4       0.000       0.000       0.000      1   1   1
*###################
*
*Tästä eteenpäin aineistoa voidaan yhdistää muihin taustadatoihin ja/tai
*tehdä yksinkertaisempaa elinaika-analyysia.
*


Ajatus on työstää tuota prosessia niin, että se toimii suurissa datoissa (satoja tuhansia yksilöitä, joita seurataan esim. viikko- kuukausitasolla). Homman voisi tehdä paloittain (esim. /FOR2 luuppisukrolla), niin että tietokannasta otetaan kerralla vain osa ja yo. prosessin jälkeen käsitelty data viedään takaisin tietokantaan (josta sitten R:llä,... tekisi varsinaiset elinaika-analyysit). Mutta tässä pääjuttu oli vähän harjoitella tuollaisen datan kanssa, jossa alku- ja loppupvm ovat ikään kuin analyysivaiheen päätettävissä. Datarakenteet voivat olla erilaisia, esim. toiset datat ovat suoraan sellaisia, joissa on tietoihina prosessin alku- ja loppupvm), tietokannassa sitten yhdistelyä.

t. Petri



*TUTSAVE ACTIVATE2
/ /ACTIVATE <char>          / S.Mustonen 26.9.1993 (6.4.1999)(28.6.2001)
/ activates all commands with <char> in the control column.
/ ACT_BREAK = 1 spec  (p.p, 20xx)
/
*{tempo -1}{init}
- if W1 '=' (empty) then goto H
- if W1 '<>' ? then goto S
+ H: {W1=SURVOACT}{call SUR-SAVE}{break on}{jump 1,1,1,1}SCRATCH {act}{R}
*{message}        Press ENTER!@
/
*/ACTIVATE +                                                 {R}
*activates commands with + in the control column successively{R}
*from the line below the /ACTIVATE line onwards.             {R}
*By default the operations activated are working under       {R}
*`interaction off' mode. To activate them in `interaction on'{R}
*mode, use an extra parameter 1 (i.e. /ACTIVATE +,1 ).       {R}
- on key
-    key _: continue
-   wait 600
*{message shadow 1}{message}@{W1=SURVOACT}{call SUR-RESTORE}{goto E}
/
/ def Wchar=W1 Winter=W2 Wcontr=W3
/
+ S: {line start}{R}
+ B: {}
/ Find next line with control character same as Wchar (W1)
*{pre}Lc
/
*{save spec ACT_BREAK W15}{line start}{l4}{save char Wcontr}{r}
- if Wcontr '<>' Wchar then goto F
- if Winter '=' {} then goto D
*{interaction on}
+ D: {save stack SUR_ACT}{act}{load stack SUR_ACT}{interaction off}
- if W15 '<>' {} then goto E
*{ref set 1}
+ C: {R}
*{goto B}
+ F: {u}
+ E: {tempo +1}{end}