spmap
¶Kartor är effektiva för att visa geografiska mönster i data. Stata har inte jättebra stöd för att göra kartor eller GIS i allmänhet, men det finns ett bra användarskapat kommando som vi kan använda för att göra fina koroplet-kartor. De visar olika variablers värden genom färger.
Kommandot heter spmap
. Vi kan ladda ned och installera det genom att skriva ssc install spmap
. Det behöver vi bara göra en gång.
Men vi behöver också geografisk data. För spmap
innebär det shapefiler som har omvandlats till koordinater som Stata kan använda. Vi kan använda kommandot shp2dta
för att omvandla vilken shapefil som helst, men det kräver en del jobb i att matcha olika id-markörer mellan dataset.
Jag har dock redan gjort detta jobb! Jag tog shapefilerna som visar landsgränser från Natural Earth, och matchade dem med länderna i QoG-databasen. Sen gjorde jag koordinatfiler som man kan använda för att rita världskartor, men också regionala kartor över Europea, Nordamerika, Sydamerika, Afrika och Asien.
Framförallt har jag använt Mercators projektion, men tyvärr förvränger den formerna på länderna kring polerna. På världskartor med Mercatorprojektionen (som Google maps bland annat använde tidigare) ser Grönland ut att vara ungefär lika stort som Afrika. I verkligheten är Afrika 14 gånger större!
Jag har därför också skapat koordinatfiler för utsnitt av Europa och Nordamerika som använder Lamberts koniska konforma projektion, som ger en mer rättvisande bild av de nordligare områdena.
Här är filerna som behövs för att rita kartorna. Den första är en ID-fil, som vi behöver för att matcha koderna i koordinatfilerna med QoG-datan. Ladda ned den, och de koordinatfiler du är intresserad av, och lägg i en projektmapp.
Sen har vi koordinatfilerna, en för varje karta. Den viktigaste är såklart världskartan, men de regionala utsnitten kan också vara bra att ha om man bara ska visa en mindre yta.
Världskarta - Mercator
Europa - Mercator
Europa - Lambert
Nordamerika - Mercator
Nordamerika - Lambert
Sydamerika - Mercator
Afrika - Mercator
Asien - Mercator
Först måste vi bestämma projektmapp så vi lätt kommer åt våra filer. Jag har sparat en nedladdad version av QoG-datan, tillsammans med ID-filen och koordinatfilerna i en speciell mapp på datorn. Vi börjar med att berätta för Stata var den mappen ligger, och laddar sedan in datamängden som ligger i mappen.
cd "/users/xsunde/Dropbox/Jupyter/stathelp/data/GIS/"
use "qog_bas_cs_jan18.dta", clear
Nu ska vi matcha ihop datan i QoG-datamängden med ID-numrena som vi behöver för att rita kartorna. Vi gör det med hjälp av merge-kommandot. Vi matchar på variabeln "ccode" som finns med i QoG-datamängden. Att det funkar att matcha ihop med den är bara för att jag har förberett koordinatfilerna på det sättet; när man gör egna koordinatfiler behöver man oftast matcha på landsnamn.
Vi använder en en-till-många merge merge 1:m
eftersom det finns fler observationer i id-filen än i QoG-datan (det handlar till exempel om små besittningar som har en egen enhetskod men tillhör ett annat land).
merge 1:m ccode using "idfile.dta", nogenerate
Nu ska vi ha fått en ny variabel i datmamängden som heter "na_id_world". Det här är ID_filen som vi ska använda när vi gör kartorna.
Låt oss först göra en karta som visar förväntad livslängd runtomkring i världen. Principen bakom spmap
är att vi först skriver kommandot, sedan variabeln som vi vill rita ut, sedan koordinatfilen, och sedan ett option för vad vår id-variabel heter. Här vi vill vi plotta variabeln "wdi_lifexp", koordinatfilen heter "coord_mercator_world.dta", och id-variabeln heter "na_id_world".
För att få kartan att se lite intressantare ut lägger vi också till ett option, fcolor(RdYlGn)
som anger färgschemat. Det blir nu sekventiellt, från rött via gult till grönt. Högre världen (alltså där folk lever längre) blir gröna. Skriv help spmap
och klicka på "colorlist" ör att se alla alternativ.
spmap wdi_lifexp using "coord_mercator_world.dta", id(na_id_world) fcolor(RdYlGn)
Inte så tokigt, men vi måste komma ihåg att regionerna i norr inte alls är så stora i verkligheten. Men vi kan göra några förbättringar av kartan. Först ställer vi in kategorigränserna med hjälp av clmethod(custom) clbreaks()
. Vi anger det i 10-årsintervall, för att göra karta överskådligare. Jag gillar också att göra gränserna mellan länderna lite svagare, vilket vi kan göra med osize() ndsize(vvthin)
I parentesen för osize skriver vi ut hur tjock linjen ska vara, men vi måste skriva det en gång för varje kategori (fyra i det här fallet). Slutligen lägger vi till en titel som förklarar kartan.
spmap wdi_lifexp using "coord_mercator_world.dta", id(na_id_world) fcolor(RdYlGn) ///
osize(vvthin vvthin vvthin vvthin) ndsize(vvthin) clmethod(custom) clbreaks(50 60 70 80 90) ///
title("Life expectancy at birth")
Mycket prydligare! Vi kan använda kommandot graph export "map.png", replace
för att spara kartan som antingen en .png eller .pdf-fil. Om den framförallt ska användas på webben är .png generellt bättre, men om den ska in i en rapport brukar .pdf ge bättre bildkvalitet.
Nu kan vi titta på några regionala utsnitt. Vi kan visserligen använda världskartan och bara välja vilka länder vi vill rita ut med hjälp av if-satser, men det kompliceras av att vissa länder har besittningar på helt andra ställen. Om vi till exempel ritar ut Frankrike får vi med avlägsna öar vid Sydamerika på kartan, vilket gör det svårt att se själva Frankrike. Därför har jag konstruerat de här regionala utsnitten, för att göra processen enklare.
För omväxlingens skull ska vi nu rita ut varje lands värde på Corruption Perceptions Index ("ti_cpi" i dataamängden). I princip ritar vi ut datan på exakt samma sätt, med samma id, fast vi använder en annan kartfil (och några andra options).
Vi tar utsnittet av Europe, och så använder vi Lamberts koniska konforma projektion. Jag har tagit bort de options som hade att göra med indelningarna av kategorierna. Slutligen har jag också lagt till ett option för att göra områden utan data gråa, för att skilja dem från haven.
spmap ti_cpi using "coord_lambert_europe.dta", id(na_id_world) fcolor(RdYlGn) ///
osize(vvthin vvthin vvthin vvthin) ndsize(vvthin) ndfcolor(gray) ///
title("Corruption Perceptions Index")
Med den här projektionen får vi en bättre känsla för hur stora länderna är. Sverige har rätt stor yta, men inte alls som Mercatorprojektionen ger sken av.
Nu kan vi prova utsnittet av Afrika, och vi plottar här nedan graden av demokrati (med variabeln p_polity2). Vi kan också använda ett annat färgschema. Här har jag angett ett som går från lila till blå till grönt. Kanske inte jättepedagogiskt, men det ser i alla fall roligt ut.
spmap p_polity2 using "coord_mercator_afr.dta", id(na_id_world) fcolor(PuBuGn) ///
osize(vvthin vvthin vvthin vvthin) ndsize(vvthin) ndfcolor(gray) ///
title("Polity index")
Notera att vi också får med delar av södra Europa på kartan. Det gör kartan mer realistisk, men det kan också verka distrahetrande. Så låt oss jämföra kartan ovan med en världskarta där vi sagt åt Stata att bara ta med länder i vissa regioner. Rent konkret blir det de som på variabeln ht_region har värdet 3 (Afrika söder om Sahara) eller 4 (Nordafrika och mellanöstern) Vi anger alltså att koordinatfilen ska vara världskartan:
spmap p_polity2 using "coord_mercator_world.dta" if ht_region==3 | ht_region==4, id(na_id_world) fcolor(PuBuGn) ///
osize(vvthin vvthin vvthin vvthin) ndsize(vvthin) ndfcolor(gray) ///
title("Polity index")
Snyggt och prydligt, men man kan också få intrycket att Iran uppe till höger är omgivet av vatten på tre sidor, vilket alltså inte stämmer. Men det är en smaksak vad som känns mest pedagogiskt!
Notera också att uppdelningen av länder har förändrats. Som default försöker Stata placera ungefär lika många länder i varje kategori. Eftersom vi nu har tagit bort alla andra länder så kan man nu hamna i toppkategorin med betydligt lägre poäng på demokrativariabeln. Datan är densamma, men kategorierna har ändrats.
ID-filen innehåller också variabler som låter oss använda data från V-dem. För att göra så laddar vi ned och öppnar V-dem-datan, som är time-series cross-section-data. Här har vi alltså information om länder, över tid. För att kunna matcha ihop det med ID-filen tar vi bort alla år utom det senaste, 2018, med keep if year==2018
.
När vi gjort det är vi redo att slå ihop datan med ID-filen. Den här gången använder vi variabeln "country_id", som är konstruerad för att matcha just med V-dem-datan.
use "../V-Dem-CY-Core-v9.dta", clear
keep if year==2018
merge 1:m country_id using "idfile.dta", nogenerate
Now we can make a map in the same way we did above. Here is a map that shows V-Dem's "Liberal democracy index" (v2x_libdem).
spmap v2x_libdem using "coord_mercator_world.dta", id(na_id_world) fcolor(RdYlGn) ///
osize(vvthin vvthin vvthin vvthin) ndsize(vvthin) title("V-Dem Liberal democracy index")
Koordinatfilerna som länkas ovan funkar alltså med QoG-variabeln "ccode". Den finns både med i cross-section och tidsserie-datan. Tyvärr ändras dock landsgränserna över tid, så man behöver olika koordinatfiler för olika tidpunkter. Några sådana historiska koordinatfiler har jag inte förberett. Samma sak gäller för V-dem-datan.
Om du vill plotta annan data än QoG-datan kan de här filerna ändå vara användbara, eftersom QoG-datan också har andra ID-nummer, som kan användas för att lägga till mer data. Till exempel så innehåller datan koder som Världsbanken använder. Använd kommandot merge för att lägga till mer data.
Ett varningens ord: När du försöker plotta data som saknas så ritar spmap
ändå ut gränserna, men färglägger det som "no data". Så vill vi generellt att det ska vara. Men om du av någon anledning använder if-satser för att välja ut observationer - till exempel för att rita ut ett visst år från V-dem-datan - så kommer spmap
att inte rita ut gränserna för de länder som inte uppfyller villkoret. Om det plötsligt försvinner länder från din karta kan det därför vara en bra idé att se efter om det är någon if-sats som utesluter landet.
Kom också ihåg att kolla in help spmap
för att se alla olika options för att ställa in kartan. Det finns mycket att göra med förklaring, färger, bakgrund och så vidare!