Månedlig, kvartalsvis og årlig nasjonalregnskap. Datokonvertering til Pandas PeriodIndex

#!/usr/bin/env python
# coding: utf-8
# Jupyter notebook versjon ligger på https://github.com/janbrus/ssb-api-python-examples

# Hente tabeller med datokonvertering
# Eksempel Nasjonalregnskap. Tabellene for nasjonalregnskap har egenskapen at de har lik struktur men ulik frekvens. 
# Da kan vi enkelt bruke samme spørring, og poste den mot ulike tabellers metadata for å hente tall
# Makroøkonomiske hovedstørrelser:
# - [09189](https://www.ssb.no/statbank/table/09189) - årlig
# - [09190](https://www.ssb.no/statbank/table/09190) - kvartalsvis
# - [11721](https://www.ssb.no/statbank/table/11721) - månedlig


# Først importerer vi ulike pakker

import requests
import pandas as pd
from pyjstat import pyjstat  # pyjstat er for behandling av JSON-stat

# URL til tabellenes metadata i PxWebApi, som vi skal poste spørringene mot

tabid = "09190" # prøv å kjøre med id for både år (09189), kvartal (09190)  og måned (11721)
lang = "no"  # vi kan velge "en"
url1 = "https://data.ssb.no/api/v0/" + lang + "/table/" + tabid;


# Vi spør etter årlig volumendring for BNP og BNP Fastlandsnorge for perioden 2010-2029 med filter all.
# API-spørring formulert som JSON.

query1 = {
  "query": [
    {
      "code": "Makrost",
      "selection": {
        "filter": "item",
        "values": [
          "bnpb.nr23_9",
          "bnpb.nr23_9fn"
        ]
      }
    },
    {
      "code": "ContentsCode",
      "selection": {
        "filter": "item",
        "values": [
          "Volum"
        ]
      }
    },
    {
      "code": "Tid",
      "selection": {
        "filter": "all",
        "values": [
         "201*",
          "202*"
        ]
      }
    }
  ],
  "response": {
    "format": "json-stat2"
  }
}

##########################
# Funksjon for identifiserer frekvens slik at vi kan konvertere til datoformat. Da kan vi kan sette Pandas RangeIndex

#funksjon for frekvenser
def dateConv(dataframe):
    frekvens, frek_no, frek_en, fmt = findFrequency(dataframe)
    setPeriodIndex(frekvens, frek_no, frek_en, fmt, dataframe)

def findFrequency(dataframe):
    frekvenser = ['måned', 'kvartal', 'uke', 'år', 'year', 'quarter', 'month', 'week']
    frek_no = ''  #SSB bruker dessverre norske frekvenskode U - uke osv.
    frek_en = '' #engelsk frekvens kode
    fmt = '' # python datoformat
    for w in frekvenser:
        if w in dataframe.columns:
            if w in ['måned', 'month']:
                frek_no = 'M'
                frek_en = 'M'
                fmt = '%YM%m'
            elif w in ['kvartal', 'quarter']:
                frek_no = 'K'
                frek_en = 'Q'
            elif w in ['uke', 'week']:
                frek_no = 'U';
                frek_en = 'W'
                fmt = '%YW%W-%w'
            else:
                frek_no = ''
                frek_en = 'A'
            return w, frek_no, frek_en, fmt


def setPeriodIndex(frekvens, frek_no, freq_en, fmt, df):
    if frekvens in ['kvartal', 'quarter']:
        # erstatter K med Q, konverterr til datoformat og setter frekensen til Pandas PeriodIndex
        df.index = pd.PeriodIndex(pd.to_datetime(df[frekvens].str.replace(frek_no, freq_en), errors='coerce'), freq='Q-DEC')
    elif frekvens in ['uke', 'week']:
        df.index = pd.PeriodIndex(pd.to_datetime(df[frekvens].str.replace(frek_no, freq_en).add('-0'), format= fmt, errors='coerce'), freq='W-MON')
    else:
        df.index =  pd.PeriodIndex(pd.to_datetime(df[frekvens], format= fmt, errors='coerce'), freq=freq_en)
############ slutt funksjoner ##########

# Her poster vi spørringen
res1 = requests.post(url1, json=query1)

# Leser resultatet med biblioteket pyjstat
ds1 = pyjstat.Dataset.read(res1.text)

# Skriver resultatet til en Pandas dataframe
df1 = ds1.write('dataframe')
df1.head(7)

# Kaller funksjonen dateConv som konverterer til dato
# Gjør en konvertering fra kategori til datoformat. Deretter settes denne som index med bruk av Pandas PeriodIndex
dateConv(df1)

# Nå har vi fått en Pandas PeriodIndex
df1.info()

# Plot med pandas groupby - gir to figurer
df1.groupby('makrostørrelse').plot( use_index=True, y='value', marker="o", markersize=3)


# ### pivoterer datasettet for å få èn figur
df2 = df1.pivot(columns = 'makrostørrelse', values='value')

# Øker størrelsen og setter SSB-farger
df2.plot(figsize=(16, 8), color=['#1a9d49', '#1d9de2'], title="BNP årlig volumendring %")