“It’s the inflation, stupid!”

Putting inflation in perspective historically and cross-sectionally by looking at data from the OECD data warehouse.

December 9, 2022

One of the major themes for the economic news cycle of 2022 has been inflation. To assess the scale and impact rising prices have had across the globe, it is interesting to look at the consumer price indices (CPI) for various countries. A consumer price index (CPI) measures the price of a weighted average market basket of consumer goods and services purchased by households. Changes in CPI track changes in prices over time. To put current inflation numbers into a historical perspective, it is interesting to look at a long-term time series of inflation.

OECD maintains an aggregated database of more than 50 national CPI indices in the OECD data warehouse. This includes long-term time series data for the USA (where OECD has data available going back to 1955) as well as an aggregate measure for all OECD countries (data available since 1970).

A long-term view on inflation

The inflation time series for the USA and OECD as a whole have a very similar dynamic and had their historical maximum in the late 70s/early 80s at a peak rate of ~15% year-on-year. For much of the last 50 years, however, inflation was in the range of 2 to 4 per cent.

Time series of US and OECD inflation

import altair as alt
import pandas as pd

def get_from_oecd(sdmx_query):
    return pd.read_csv(

long_countries = ['USA', 'OECD']

cpi_long = get_from_oecd("PRICES_CPI/%s.CPALTT01.GY.M/all?startTime=1950&endTime=2022&contentType=csv" % "+".join(long_countries))
cpi_long['Value'] /= 100
cpi_long['TIME'] = pd.to_datetime(cpi_long.TIME)

cpi_long['Country'] = cpi_long['Country'].replace({'OECD - Total': 'OECD'})

selection = alt.selection_multi(fields=['Country'], bind='legend')

    x=alt.X('TIME:T', title=''),
    y=alt.Y('Value:Q', title='Inflation (YoY)', axis=alt.Axis(format="%")),
             alt.Tooltip('TIME', format='%b %Y', title='Date'),
             alt.Tooltip('Value', format=".1%", title='Inflation (YoY)')]

Source: OECD (2022), Inflation (National CPI, % change vs. prior year, seasonally adjusted). doi: 10.1787/eee82e6e-en

Comparing inflation across countries

OECD aggregates national CPI data from a range of European and other developed as well as emerging market countries. It is interesting to compare the time series data across countries.

Cross-sectional inflation data for 44 European, other DM and EM countries

import datetime

countries = ['AUS', 'AUT', 'BEL', 'CAN', 'CHL', 'COL', 'CRI', 'CZE', 'DNK',
             'EST', 'FIN', 'FRA', 'DEU', 'GRC', 'HUN', 'ISL', 'IRL', 'ISR',
             'ITA', 'JPN', 'KOR', 'LVA', 'LTU', 'LUX', 'MEX', 'NLD', 'NZL',
             'NOR', 'POL', 'PRT', 'SVK', 'SVN', 'ESP', 'SWE', 'CHE', 'TUR',
             'GBR', 'USA', 'EA19', 'EU27_2020', 'G-7', 'OECDE', 'G-20', 'OECD',
             'NMEC', 'ARG', 'BRA', 'CHN', 'IND', 'IDN', 'RUS', 'SAU', 'ZAF']

cpi = get_from_oecd("PRICES_CPI/%s.CPALTT01.GY.M/all?startTime=2012&endTime=2022&contentType=csv" % "+".join(countries))
cpi['Value'] /= 100
cpi['TIME'] = pd.to_datetime(cpi.TIME)

region_order = ['Europe', 'Other DM', 'Emerging Markets']

country_replacements = {
    "China (People's Republic of)": 'China',
    'Slovak Republic': 'Slovakia'

country_region_map = {
    'Austria': 'Europe',
    'Belgium': 'Europe',
    'Denmark': 'Europe',
    'Czech Republic': 'Europe',
    'Estonia': 'Europe',
    'Finland': 'Europe',
    'France': 'Europe',
    'Germany': 'Europe',
    'Greece': 'Europe',
    'Hungary': 'Europe',
    'Iceland': 'Europe',
    'Ireland': 'Europe',
    'Italy': 'Europe',
    'Latvia': 'Europe',
    'Lithuania': 'Europe',
    'Luxembourg': 'Europe',
    'Netherlands': 'Europe',
    'Norway': 'Europe',
    'Poland': 'Europe',
    'Portugal': 'Europe',
    'Slovakia': 'Europe',
    'Slovenia': 'Europe',
    'Spain': 'Europe',
    'Sweden': 'Europe',
    'Switzerland': 'Europe',
    'United Kingdom': 'Europe',
    'Canada': 'Other DM',
    'Israel': 'Other DM',
    'Japan': 'Other DM',
    'Korea': 'Other DM',
    'United States': 'Other DM',
    'Brazil': 'Emerging Markets',
    'Chile': 'Emerging Markets',
    'China': 'Emerging Markets',
    'Colombia': 'Emerging Markets',
    'India': 'Emerging Markets',
    'Indonesia': 'Emerging Markets',
    'Mexico': 'Emerging Markets',
    'Russia': 'Emerging Markets',
    'Saudi Arabia': 'Emerging Markets',
    'South Africa': 'Emerging Markets',
    # 'Argentina': 'Other',
    # 'Türkiye': 'Other',
    # 'Costa Rica': 'Other',
    # 'Euro area (19 countries)': 'Other',
    # 'European Union – 27 countries (from 01/02/2020)': 'Other',
    # 'G20': 'Other',
    # 'G7': 'Other',
    # 'OECD - Europe': 'Other',
    # 'OECD - Total': 'Other',

cpi['Country'] = cpi['Country'].apply(lambda c: country_replacements[c] if c in country_replacements else c)
cpi['Region'] = cpi['Country'].apply(lambda c: country_region_map.get(c, None))

date_start = datetime.datetime(2012, 10, 1)
date_end = datetime.datetime(2022, 10, 1)

plot_df = cpi.loc[(cpi.TIME > date_start) & (cpi.TIME <= date_end), ['Country', 'Region', 'Value', 'TIME']]

color_lower = -0.02
color_upper = 0.1

plot_df['Color'] = plot_df['Value'].clip(lower=color_lower, upper=color_upper)

charts = []

for r in region_order:
    chart_df = plot_df[plot_df['Region'] == r]
    chart = alt.Chart(chart_df).mark_rect(opacity=0.9).encode(
        x=alt.X('yearmonth(TIME):T', axis=alt.Axis(format="%Y" if r == region_order[-1] else " ", tickCount='year' if r == region_order[-1] else 0), title=''),
        y=alt.Y('Country:O', title=r),
        color=alt.Color('Color:Q', title='Inflation', scale=alt.Scale(scheme='redyellowgreen', reverse=True, domain=[color_lower, color_upper]), legend=alt.Legend(format=".0%")),
                 alt.Tooltip('TIME', title='Date', format='%b %Y'),
                 alt.Tooltip('Value', title='Inflation (YoY)', format=".1%")]
        height=len(set(chart_df['Country'])) * 15,