# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# +
import re

import pandas as pd
import altair as alt
import numpy as np
# -

# ### Notes
#
# 1. Data is from https://www.imf.org/external/datamapper/PCPIPCH - download all data as Excel file
# 2. The data is in old-Excel format. I used LibreOffice Calc to save it as new XLSX format
# 3. For 2-letter and 3-letter ISO country codes, I used a CSV file from https://gist.githubusercontent.com/tadast/8827699/raw/f5cac3d42d16b78348610fc4ec301e9234f82821/countries_codes_and_coordinates.csv
# 4. The AU website was misbehaving, so I used an archive.org copy of https://web.archive.org/web/20210424163337/https://au.int/en/member_states/countryprofiles2 for AU member states and regions
#
# ### Python modules
#
# Python modules are installed using [conda](https://docs.conda.io/en/latest/). The main modules are pandas, altair, lxml, pyarrow and fastparquet, but my complete `environment.yml` can be found in this notebook's Github repository.

imf_inflation_data = pd.read_excel('data/imf-dm-export-20210525.xlsx', sheet_name='PCPIPCH')
imf_inflation_data.columns = ['country'] + list(imf_inflation_data.columns[1:])  # rename first column to country
imf_inflation_data = imf_inflation_data.drop(0).drop(227).drop(226)  # drop rows not containing data
imf_inflation_data = imf_inflation_data.set_index('country')  # index by country
imf_inflation_data = imf_inflation_data.drop(labels=[year for year in range(2021,2027)], axis=1)  # drop all projected inflation rates
imf_inflation_data


# +
def strip_to_str(val: str) -> str:
    return re.sub(r'\s{0,}"([^"]+)"', r"\1", val)

def strip_to_int(val: str) -> int:
    return int(strip_to_str(val))

def strip_to_float(val: str) -> float:
    return float(strip_to_str(val))

country_code_df = pd.read_csv('https://gist.githubusercontent.com/tadast/8827699/raw/f5cac3d42d16b78348610fc4ec301e9234f82821/countries_codes_and_coordinates.csv', 
                              quotechar='"', skiprows=1, converters={
                                  'alpha_2': strip_to_str, 'alpha_3': strip_to_str,
                                  'numeric': strip_to_int, 'latitude_avg': strip_to_float, 'longitude_avg': strip_to_float
                              },
                              index_col=0, names=['country', 'alpha_2', 'alpha_3', 'numeric', 'latitude_avg', 'longitude_avg'])
country_code_df

# + tags=[]
tables = pd.read_html('https://web.archive.org/web/20210424163337/https://au.int/en/member_states/countryprofiles2', header=0)
# -

central_africa_df = tables[2]
east_africa_df = tables[3]
north_africa_df = tables[4]
south_africa_df = tables[5]
west_africa_df = tables[6]
all_africa_df = pd.concat([central_africa_df, east_africa_df, north_africa_df, south_africa_df, west_africa_df])

# +
africa_country_to_imf_name = {
    'Congo Republic': 'Congo, Republic of ',
    'DR Congo': 'Congo, Dem. Rep. of the',
    'São Tomé and Príncipe': 'Sao Tome and Principe',
    'Tanzania': 'Tanzania, United Republic of',
    'Eswatini': 'Swaziland',
    'Cabo Verde': 'Cape Verde',
    'Côte d’Ivoire': "Côte d'Ivoire",
    'South Sudan': 'South Sudan, Republic of',
    'Gambia': 'Gambia, The'
}

africa_country_to_name = {
    'Congo Republic': 'Congo',
    'DR Congo': 'Congo, the Democratic Republic of the',
    'São Tomé and Príncipe': 'Sao Tome and Principe',
    'Tanzania': 'Tanzania, United Republic of',
    'Eswatini': 'Swaziland',
    'Cabo Verde': 'Cape Verde',
    'Côte d’Ivoire': "Côte d'Ivoire",
    'South Sudan': 'South Sudan, Republic of',
    'Gambia': 'Gambia, The'
}
for country in all_africa_df.Abbreviation:
    if country not in country_code_df.index:
        if country not in africa_country_to_name:
            print(country)
# -

data = {}
for country in all_africa_df.Abbreviation:
    if country in central_africa_df.Abbreviation.values:
        region = 'central'
    elif country in east_africa_df.Abbreviation.values:
        region = 'east'
    elif country in north_africa_df.Abbreviation.values:
        region = 'north'
    elif country in south_africa_df.Abbreviation.values:
        region = 'south'
    elif country in west_africa_df.Abbreviation.values:
        region = 'west'
    else:
        raise ValueError('Unknown country: ' + country)

    if country in ('Sahrawi Republic', 'Somalia'):
        # we don't have info from IMF for these two countries
        continue
    elif country in country_code_df.index:
        lookup_name = country
    elif country in africa_country_to_name:
        lookup_name = africa_country_to_name[country]
    else:
        raise ValueError('Cannot lookup country: ' + country)
    
    code_2 = country_code_df.loc[lookup_name, 'alpha_2']
    code_3 = country_code_df.loc[lookup_name, 'alpha_3']
    
    if country in imf_inflation_data.index:
        lookup_name = country
    elif country in africa_country_to_imf_name:
        lookup_name = africa_country_to_imf_name[country]
    
    inflation_data = list(imf_inflation_data.loc[lookup_name])
    data[country] = [region, code_2, code_3] + inflation_data
inflation_df = pd.DataFrame.from_dict(data, orient='index', columns=['region', 'alpha_2', 'alpha_3'] + list(imf_inflation_data.columns)).replace('no data', np.nan)
inflation_df.index.name = 'country'
inflation_df

# write the data in Excel, CSV and Parquet formats
inflation_df.to_excel('data/africa_inflation_data.xlsx', sheet_name='Inflation')
inflation_df.to_csv('data/africa_inflation_data.csv')
inflation_df.columns = [str(column) for column in inflation_df.columns]
inflation_df.to_parquet('data/africa_inflation_data.parquet')
# Parquet is a format that retains the complete DataFrame structure and can be read back quite simply:
# pd.read_parquet('data/africa_inflation_data.parquet')

# ### Long form and plotting
#
# When plotting data with e.g. Altair, the data should be in [*long form*](https://altair-viz.github.io/user_guide/data.html#long-form-vs-wide-form-data), that is, one row per observation with metadata (e.g. year names) as values in the dataframe.
#
# The next code reformats the data into long form and then illustrates plotting with Altair

inflation_longform_df = inflation_df.reset_index().melt(['country', 'region', 'alpha_2', 'alpha_3'], var_name=['year'], value_name='inflation')
inflation_longform_df

alt.Chart(inflation_longform_df[inflation_longform_df.country.isin(['South Africa', 'Kenya'])]).mark_line().encode(x=alt.X('year:O', title='Year'),
                                                                                                                   y=alt.Y('inflation', title='Inflation (%)'),
                                                                                                                   color='country',
                                                                                                                   tooltip=['country', 'alpha_3']
                                                                                                                  )





StarcoderdataJupyterScriptsDedupFiltered