Koda om variabler

av Anders Sundell

Oftast när vi jobbar med dataanalys är det inte vi själva som konstruerat datamängden. Då är det troligt att variablerna inte passar perfekt med våra syften. Vi kanske bara är intresserade av några särskilda kategorier, vill göra specifika jämförelser, eller använda andra indelningar. Då behöver vi göra så kallade omkodningar. Det innebär att vi skapar nya variabler, utifrån de gamla.

För detta finns det i Stata en mängd olika kommandon. I den här guiden kommer vi att gå igenom tre av de mest användbara: recode, generate och replace.

För att ha något att jobba med kommer vi att använda oss av QoG basic-datamängden. Här har jag skrivit in sökvägen till datamängden direkt på internet, men man kan givetvis ladda ned den till sin dator och öppna den därifrån istället - det är vanligtvis att rekommendera.

In [6]:
use "https://www.qogdata.pol.gu.se/data/qog_bas_cs_jan18.dta", clear
(Quality of Government Basic dataset 2018 - Cross-Section)

Recode

Recode-kommandot bygger på att man byter ut olika värden på en variabel mot något annat. Man kan byta ut enskilda värden, eller olika "ranges", dvs 5-19 eller 28-752.

Vi kan till exempel titta på organisationen Freedom House's kategorisering av världens länder som "Free," "Partly free," och "Not free." Vi gör det med kommandot tab, som visar hur många analysenheter som har respektive värde.

In [10]:
tab fh_status
    Freedom |
     Status |      Freq.     Percent        Cum.
------------+-----------------------------------
       Free |         89       45.88       45.88
Partly Free |         54       27.84       73.71
   Not Free |         51       26.29      100.00
------------+-----------------------------------
      Total |        194      100.00

89 länder har värdet "Free", 54 "Partly free" och 51 "Not free." Nu är det i datamängden inte så att de orden är inkodade. Istället är variabeln sparad som siffervärden, och så har varje värde en etikett. För att kolla på de faktiska värdena kan vi lägga till ett option på tab-kommandot, nolabel:

In [11]:
tab fh_status, nolabel
    Freedom |
     Status |      Freq.     Percent        Cum.
------------+-----------------------------------
          1 |         89       45.88       45.88
          2 |         54       27.84       73.71
          3 |         51       26.29      100.00
------------+-----------------------------------
      Total |        194      100.00

Det här är de värden som Stata faktiskt räknar med. Free har alltså värdet 1, Partly free har värdet 2 och Not free värdet 3. Om vi vill koda om variabeln måste vi använde de här sifferkoderna, inte orden "Free" osv.

Låt oss nu säga att vi vill särskilja demokratierna, länderna som har värdet "Free." Vi vill göra en ny variabel som är 1 för demokratier, och 0 för ickedemokratier. Omkodningen vi vill göra är alltså:

1 → 1
2 → 0
3 → 0

För detta kan vi använda recode-kommandot. Strukturen är att man skriver recode, vilken variabel man ska omkoda, hur den ska omkodas, och sen ett option som berättar vad den nya variabeln ska heta. Vi vill inte ändra på den ursprungliga variabeln.

In [15]:
recode fh_status (1 = 1) (2 3 = 0), generate(democracy)
(105 differences between fh_status and democracy)

Varje parentes innehåller de gamla värdena till vänster, och det nya värdet till höger. 1 ska alltså bli till 1, 2 och 3 ska bli till noll. Och den nya variabeln ska heta demokrati. Sen ska man alltid dubbelkolla att det blev rätt:

In [17]:
tab democracy
  RECODE of |
  fh_status |
   (Freedom |
    Status) |      Freq.     Percent        Cum.
------------+-----------------------------------
          0 |        105       54.12       54.12
          1 |         89       45.88      100.00
------------+-----------------------------------
      Total |        194      100.00

Det är fortfarande 194 länder, 89 länder har värdet 1, och 105 har värdet 0. Det stämmer bra eftersom det var 54+51=105 som hade värdena 2 och 3 på den gamla variabeln.

Om man inte vill lista alla enskilda värden kan man använda sig av / för att uttrycka ett intervall. Om vi till exempel skulle koda om variabeln fh_rol, som visar landets grad av "Rule of law." Variabeln har värdena 0-16, och vi kanske vill att de som har värdet 10-16 ska få en etta på en ny variabeln, och de som har värdet 0-9 ska få en nolla.

In [14]:
recode fh_rol (0/9 = 0) (10/16 = 1), generate(highruleoflaw)
(183 differences between fh_rol and highruleoflaw)

Generate

Man kan också göra variabler "från scratch." Kommandot generate skapar en ny variabel i datamängden. Kombinerad med if-satser - villkor som bara tillämpar kommandot på vissa analysenheter - och replace, som vi går igenom strax, är det ett mycket flexibelt verktyg.

Strukturen är att man skriver generate, namnet på den nya variabel man vill göra, och sedan vad variabeln ska ha för värde. Vi kan till exempel göra en test-variabel som har värdet 0 för alla analysenheter. Jag använder här förkortningen "gen", som går lika bra att skriva som generate:

In [27]:
gen test = 0
In [28]:
tab test
       test |      Freq.     Percent        Cum.
------------+-----------------------------------
          0 |        194      100.00      100.00
------------+-----------------------------------
      Total |        194      100.00

194 länder har nu fått värdet 0 på den nya variabeln test. Inte så användbart, än så länge. Men man kan också använda generate för att göra nya varianter av existerande variabler. Datamängden innehåller till exempel en variabel för ländernas BNP per capita, gle_rgdpc. Den är uttryckt som antalet dollar BNP per invånare. Vi kan med kommandot summarize (kan förkortas sum) bland annat se medel, min och max-värde för variabeln:

In [29]:
sum gle_rgdpc
    Variable |        Obs        Mean    Std. Dev.       Min        Max
-------------+---------------------------------------------------------
   gle_rgdpc |        192     12596.3     15803.7     285.95   95696.97

Medelvärdet är 12596,3 dollar, och maxvärdet är 95696,97. Låt säga att vi hellre skulle vilja att variabeln var uttryckt i antal tusen dollar. Vi gör då en ny variabel, som är den gamla variabeln delat på 1000. Det gör vi lätt med generate. Efter likamedtecknet kan man skriva vilken matematisk operation som helst:

In [30]:
gen bnpcap_1000 = gle_rgdpc/1000
(2 missing values generated)
In [31]:
sum gle_rgdpc bnpcap_1000
    Variable |        Obs        Mean    Std. Dev.       Min        Max
-------------+---------------------------------------------------------
   gle_rgdpc |        192     12596.3     15803.7     285.95   95696.97
 bnpcap_1000 |        192     12.5963     15.8037     .28595   95.69697

När vi jämför den gamla och den nya variabeln ser vi att det är exakt lika många länder, och siffrorna är desamma, men decimaltecknet har flyttats tre steg åt vänster. Medelvärdet är nu 12,5963 istället för 12596,3. Så länge vi kommer ihåg att den nya variabeln visar BNP/capita i tusentals dollar spelar det ingen som helst roll för analyserna, men det kan bli lättare att visa i tabeller.

Replace

Replace liknar generate-kommandot, men här ändrar vi i befintliga variabler istället för att göra nya. Ofta gör man först en variabel med generate, och ändrar sedan på den utifrån några uppsatta villkor med replace. Här får vi använda if-satser.

Vi kanske till exempel vill göra en variabel som har värdet 1 om landet är riktigt fattigt, och har en BNP per capita som är mindre än 1000 dollar. Alla andra länder ska få värdet 0. Vi börjar då med att göra en variabel där alla länder har värdet 0:

In [32]:
gen poor = 0

Sen är det dags att ändra så att de fattiga länderna får värdet 1. Det gör vi med replace-kommandot. Man skriver replace, variabeln man vill ändra på, sedan vad den ska få för värde, och sedan eventuella if-satser. If-satserna kan använda sig information från andra variabler.

In [33]:
replace poor = 1 if gle_rgdpc < 1000
(19 real changes made)

Vi ser nu att det gjordes 19 förändringar i variabeln - 19 länder fick värdet 1. Alla de har ett värde på gle_rgdpc som är lägre än 1000.

Men här har det också smugit in sig ett problem. Om vi nu skulle kolla på den nya variabeln skulle vi märka att vi hade data för 194 länder. Men om man tittar på variabeln gle_rgdpc så finns det där bara data för 192 länder. För 2 länder saknar vi information; de är "missing." I Stata har de värdet "." på variabeln, alltså en punkt. Analysenheter som har detta "missing"-värde ingår inte i analyser vi gör, vilket är bra.

När vi gjorde vår nya "poor"-variabel hade vi inget villkor inbyggt, och även dessa två länder fick värdet 0. När vi sedan ändrade på variabeln replace undersökte Stata om de hade ett värde som var under 1000 på gle_rgdpc, och det hade de inte, eftersom de hade värdet ".". Därför står de kvar som nollor. Värt att veta är att Stata (av någon okänd anledning) betraktar denna punkt som det största värdet som finns. Så om villkoret hade varit att man skulle ha ett värde på gle_rgdpc som var större än 1000 skulle de ha fått värdet 1! Det är inte riktigt intuitivt, men nödvändigt att veta.

Hur som helst vill vi inte att de här två länderna som vi inte vet något om ska vara med i vår variabel överhuvudtaget. Vi tar därför och använder replace en gång till, för att ge dem värdet . på den nya variabeln.

In [34]:
replace poor = . if gle_rgdpc == .
(2 real changes made, 2 to missing)

En intressant sak att notera är att jag i if-satsen använde dubbla likamedtecken. Det är också lite svårt att greppa, men är standard för hur man skriver sådana här villkor. De olika villkor man har att välja på är:

lika med: ==
större eller lika med: >=
mindre eller lika med: <=
inte lika med: !=
större än: >
mindre än: <
och: &
eller: |

De två sista kan användas för att kombinera olika villkor. Till exempel om vi ska skilja ut länder som både är fattiga och diktaturer:

In [35]:
gen poordictatorship = 0
In [36]:
replace poordictatorship = 1 if gle_rgdpc < 1000 & fh_status==3
(5 real changes made)

Avslutning

Det här var några alternativ för att koda om och göra nya variabler. Med dem kommer man väldigt långt, men det finns fler. De är inte heller ömsesidigt uteslutande. Det man kan göra med recode kan man ofta göra med replace, och vice versa. Man använder det man känner sig mest bekväm med, och som passar bäst för just den omkodning man är ute efter. Men kom ihåg att dubbelkolla så att det blev rätt efteråt!