Öppna data 1 – SuperSOM med Python och Pandas

I en ‘post factual’ demokrati tror vissa att öppen vetenskap kan ge människor förnuftet tillbaka. Om detta vet vi mycket lite, eftersom vi inte har så mycket fakta att gå på (vilket kan betraktas som lite ironiskt).

Men, något kan man ändå veta. För att öppen vetenskap ska bli användbar av både forskare och allmänhet (framförallt då öppna data) så måste den göras begripbar. När det kommer till kvantitativa data så underlättar det om man antingen har kunskap och licenspengar att köpa och lära sig Excel eller SPSS. Men, om man istället vill vara öppen hela vägen så är det mycket bättre att köra helt med open source. Och om man dessutom vill slå flera flugor i en smäll tar man och lär sig ett programmeringsspråk. Då kan man göra tusen andra saker än bara analysera data.

Ett bra programmeringsspråk för statistik är R eftersom det i standardutförande gör allt man behöver för att använda sig av de datastrukturer som är bra för att analysera statistisk data.

Själv använder jag Python. Det är ett mera generellt språk, men med biblioteket Pandas får man enkla färdiga datastrukturer som är väldigt lätta att använda.

I denna lilla anteckning tänkte jag lägga ut lite kodsnuttar för att analysera SOM-institutets långa tidsserie 1986-2014, även kallad ”SuperSOM”, med Python/Pandas. Det är en guldgruva för samhällsvetare och det är svårt att hitta enkätdata med högre kvalitet i Europa. Dock innehåller denna datamängd mer än 93 tusen enkätsvar, så man får ha lite tålamod och RAM-minne till hands.

SuperSOM1 är öppen data, men den är inte superöppen. Man måste beställa den från Svensk Nationell Datatjänst och tillgängligheten bestäms av ”primärforskaren”. Så man måste ange vad man ska ha datamängden till och sedan får man en nedladdningslänk. Man får inte sprida den vidare.

Tyvärr levererar inte SND i csv-format utan bara i statistikprogramformat. Så jag beställde Excel-format (som smidigt kan konverteras till csv, se nedan).

Först konvertering från Excel till csv med två enkla rader:

import pandas as pd
df = pd.read_excel('data/SND 0905-004 Super-Riks-SOM 1986-2014.xlsx') # öppna Excelfil
df.to_csv("SuperSOM1986-2014.csv", sep='\t', encoding='utf-8') # skriv till csv-fil

 

Observera att det kan ta lite tid att konvertera. Excel-formatet är lite långsamt av sig. Men när det är klart kan man läsa in csv-filen på några sekunder (tar ca. 2 Gb i minne, så bör funka på vanlig dator).

df = pd.read_csv('data/SuperSOM1986-2014.csv', sep='\t', encoding='utf-8')

Nu är hela SuperSOM inläst som en ”dataframe” och allokerad som variabeln df. För att kolla att all data är med i leken kan vi göra en enkel graf år för år med det lättanvända biblioteket Seaborn.

import seaborn as sns
years = sns.factorplot('year', data=df, kind='count', size=8, aspect=2)
years.set_xticklabels(rotation=30)

Japp, SOM-enkäten blir mycket större med åren. Däremot minskar svarsfrekvensen, något man får ha i bakhuvudet.

Därefter kan man ta fram kodboken man får med och sedan börja analysera datan. Som exempel tänker jag ta fråga md10 som frågar hur nöjd man är med livet (det man kallar för ”Life satisfaction” i internationell forskning). Om man vill få ut data i procent för varje år i en tabell får man göra lite handpåläggning (tar gärna emot tips på hur man kan göra detta med mindre kod).

Så här gjorde jag (med lite hjälp av biblioteket tabulate)

from tabulate import tabulate

def lstimeseries():
    tsresults = []
    for y in range(1996, 2015):
        year = y
        md10table = df['md10'].loc[df['year'] == year]
        #md10table = df['md10']
        md10total = 0
        mycketnojd = 0
        ganskanojd = 0
        intesarskiltnojd = 0
        inteallsnojd = 0 
        nan = 0
        for t in md10table:
            if pd.isnull(t):
                nan += 1
            elif t == 98:
                nan += 1
            elif t == 99:
                nan += 1
            elif t == 96:
                nan += 1
            elif t == 1:
                mycketnojd += 1
                md10total += 1
            elif t == 2:
                ganskanojd += 1
                md10total += 1
            elif t == 3:
                intesarskiltnojd += 1
                md10total += 1
            elif t == 4:
                inteallsnojd += 1
                md10total += 1
        # Append the data to a lis of lists that can be tabulated:
        # add , 2 to the round method to get some decimals e.g. round((mycketnojd/md10total * 100), 2)
        tsresults.append([year, round((mycketnojd/md10total * 100)),   
                           round((ganskanojd/md10total * 100)),
                           round((intesarskiltnojd/md10total * 100)),
                           round((inteallsnojd/md10total * 100))])
    return(tsresults)

print("Nöjd med livet, nationella SOM-undersökningen\n")
# For html, add , tablefmt="html"
print(tabulate(lstimeseries(), headers=["Year", "Mycket nöjd", "Ganska nöjd", 
                                        "Inte särskilt nöjd", "Inte alls nöjd"])) 

Vilket ger:

Year Mycket nöjd Ganska nöjd Inte särskilt nöjd Inte alls nöjd
1996 30 64 6 0
1997 30 61 8 2
1998 28 63 8 1
1999 29 62 8 1
2000 31 61 7 1
2001 32 60 8 1
2002 29 62 8 1
2003 33 58 8 1
2004 33 59 7 1
2005 32 59 7 1
2006 35 57 7 1
2007 35 58 7 1
2008 34 58 7 2
2009 36 57 7 1
2010 36 57 6 1
2011 37 56 6 1
2012 35 58 6 1
2013 36 57 7 1
2014 37 56 6 1

För säkerhets skull kan man kolla att man har räknat rätt genom att kontrollera mot någon av alla de rapporter som SOM-institutet publicerat. Exempelvis en intressant studie av Brülde och Nilsson från 2010.

Det verkar alltså som att vi blir allt mer ”intensivt nöjda” med livet för varje år som går. Missnöjdheten är däremot stabilt låg.

Således har vi tagit fram lite data som vi kan visa för alla kommentatorer  ”känner” det ena och det andra i samtiden. Samtidigt har vi replikerat SOM-institutets mätningar, något som är viktigt för att öka den vetenskapliga kvaliteten. Ju fler ögon desto färre buggar.


  1. Göteborgs universitet, SOM-institutet. (2016). Super-Riks-SOM 1986-2014. Version 1.0. Svensk Nationell Datatjänst. http://dx.doi.org/10.5878/002826 

1 reaktion till “Öppna data 1 – SuperSOM med Python och Pandas”

  1. ”He suggested that the current lack of public and political engagement in fact-based decision-making means the world has entered a ”post-factual” era of democracy.”

    Jag undrar om inte Carlos Moedas blandar ihop anti-fakta med ”post-fakta-demokrati-era”. Deleuze förståelse av forskning kan vara en hjälp även för att förstå demokrati. Forskning ägnar sig åt osäkerhet, frågor och problem snarare än vet-skapande. När vi vet, när det finns fakta så kan vi lämna frågan bakom oss. ”Jaoo jorden är rund inte platt.”

    Demokrati, när osäkerhet tvingar oss att ta beslut tillsammans för att lösa gemensamma problem, bör givetvis ta hänsyn till fakta. Men demokrati, som teori, ägnar sig snarare åt frågor där fakta och vetande inte ger svar. Ifall fakta ger ett svar så är demokrati irrelevant eller undanträngd.

    Fakta-baserade-frågor är frågor där demokratin ersätts med experter, exempelvis kirurger och ingenjörer. Visst, även experter kan ju behöva en demokratisk diskussion mellan sig när fakta inte ger svaret. Även experter kan tvingas ta beslut (alltså inte bara läsa av resultatet).

    Men om en skulle försöka bygga en fakta-baserad-demokrati så skulle demokratin trängas undan. Även beslutande och funderande skulle ju trängas undan. Det skulle ersättas med att läsa av resultat (att 2+2=4 är inte ett beslut eller en demokrati utan att läsa av ett resultat).

    Tja, vi lever även i en komplex värld inte bara i en linjär värld.

Kommentera

E-postadressen publiceras inte. Obligatoriska fält är märkta *

Time limit is exhausted. Please reload CAPTCHA.