Decoupling GDP from CO2 Emission - Only If You’re Rich Enough?

Developed countries were able to decoupled their GDP from CO2 emissions, while in developing countries, CO2 emissions is an inevitable consequences of their economic growth.

energy
CO2
economy
Author

Aditya Arie Wijaya

Published

July 23, 2023

CO2 Emission vs GDP

Our World in Data (OWID) shows some examples from a country that was able to decoupled their economy from CO2 emission. Meaning that they still able to increase their GDP while at the same time reducing CO2 emission. UK is the example used in Figure 1.

Figure 1: United Kingdom Decoupled CO2 Emission vs Economic Growth

You can read the full article, but I am going to quote paragraph that interest me to write this article.

“These countries show that economic growth is not incompatible with reducing emissions.”

This narrative means that you can grow your economy without emitting more emission - a bold statement considering the other chart from Figure 2 showed the opposite, where the GDP of a country is strongly related to the CO2 emission.

Even OWID themselves explained:

“Historically, CO2 emissions have been strongly correlated with how much money we have. This is particularly true at low-to-middle incomes. The richer we are, the more CO2 we emit. This is because we use more energy – which often comes from burning fossil fuels.” (source: Our World in Data)

Figure 2: CO2 Emission per Capita vs GDP per Capita

Here is where It got me concerned. There should be a big asterix on a narrative that countries can grow their economy while also reducing emission - Only when they are rich.

The premise is simple, country needs energy to grow their economy, the higher the energy consumption the higher the CO2 emission would be. I think the narrative that a country emits more CO2 because they are rich can be misleading. I think it is the other way around.

So not because we are rich we emit more CO2, but we are rich because we emit more CO2 used for energy, to grow the economy.

This is of course no to undermine the impact of CO2 emission to our global temperature, but rather to manage our expectations and a reality check on what can really be done. Some questions about “can we reduce our CO2 emission but still maintaining economy growth”? Or “do we have to increase our CO2 to raise our economic growth?” are some fair questions to be addressed in more detail.

Despite some articles pointed out the fact that some countries were able to decoupled their economy from CO2 emission as shown in Figure 1, it is important to understand the context, in which these countries were positioned compared to rest of the world.


This article will explore that question.

What allows these countries to decouple their economy from their emissions?

Data Importing and Cleaning

I explored the CO2 emission dataset provided by the OWID (Our World in Data). I will be focusing mainly on the CO2 emission and it’s impact to GDP of a country. My premise stays the same, that a country must burn the energy to grow their economy, and to do that they will have to emit CO2, since more than 80% of energy (see Figure 3) in the world still comes from fossil-fuels (oil, gas, coal).

Figure 3: Global Energy Consumption

The dataset is downloaded from the provided link in the code block below.

Show Code
#importing dataset

import pandas as pd
import warnings

# Ignore future warnings
warnings.simplefilter(action='ignore', category=FutureWarning)
pd.options.mode.chained_assignment = None  # default='warn'

co2_raw = pd.read_csv('https://raw.githubusercontent.com/owid/co2-data/master/owid-co2-data.csv')
co2_remark = pd.read_csv('https://raw.githubusercontent.com/owid/co2-data/master/owid-co2-codebook.csv')
co2_raw
country year iso_code population gdp cement_co2 cement_co2_per_capita co2 co2_growth_abs co2_growth_prct ... share_global_other_co2 share_of_temperature_change_from_ghg temperature_change_from_ch4 temperature_change_from_co2 temperature_change_from_ghg temperature_change_from_n2o total_ghg total_ghg_excluding_lucf trade_co2 trade_co2_share
0 Afghanistan 1850 AFG 3752993.0 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 Afghanistan 1851 AFG 3767956.0 NaN NaN NaN NaN NaN NaN ... NaN 0.165 0.000 0.000 0.000 0.0 NaN NaN NaN NaN
2 Afghanistan 1852 AFG 3783940.0 NaN NaN NaN NaN NaN NaN ... NaN 0.164 0.000 0.000 0.000 0.0 NaN NaN NaN NaN
3 Afghanistan 1853 AFG 3800954.0 NaN NaN NaN NaN NaN NaN ... NaN 0.164 0.000 0.000 0.000 0.0 NaN NaN NaN NaN
4 Afghanistan 1854 AFG 3818038.0 NaN NaN NaN NaN NaN NaN ... NaN 0.163 0.000 0.000 0.000 0.0 NaN NaN NaN NaN
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
50593 Zimbabwe 2017 ZWE 14751101.0 2.194784e+10 0.469 0.032 9.596 -0.937 -8.899 ... NaN 0.114 0.001 0.001 0.002 0.0 115.00 27.71 0.910 9.486
50594 Zimbabwe 2018 ZWE 15052191.0 2.271535e+10 0.558 0.037 11.795 2.199 22.920 ... NaN 0.114 0.001 0.001 0.002 0.0 116.76 29.37 0.771 6.537
50595 Zimbabwe 2019 ZWE 15354606.0 NaN 0.570 0.037 11.115 -0.681 -5.772 ... NaN 0.113 0.001 0.001 0.002 0.0 116.03 28.70 0.978 8.795
50596 Zimbabwe 2020 ZWE 15669663.0 NaN 0.570 0.036 10.608 -0.507 -4.559 ... NaN 0.112 0.001 0.001 0.002 0.0 113.20 25.99 1.006 9.481
50597 Zimbabwe 2021 ZWE 15993525.0 NaN 0.570 0.036 11.296 0.688 6.488 ... NaN 0.111 0.001 0.001 0.002 0.0 NaN NaN NaN NaN

50598 rows × 79 columns


There are over 70 columns in the original dataset, so we will only use columns that we are interested in, mainly related to GDP and CO2 emission of a country, referenced by year. Some data cleaning (removing any null rows in GDP per Capita, or CO2 consumption per Capita, etc.).

Show Code
#selecting dataset
co2 = co2_raw[[ 'country', 'year','population', 'gdp', 'co2_per_capita', 'consumption_co2_per_capita' ]]

#adding gdp per capita column
co2['gdp_per_capita'] = co2['gdp']/ co2['population']

# dropping any rows with null consumption_co2_per_capita
co2 = co2[~co2.consumption_co2_per_capita.isnull()].reset_index(drop=True)

#drop gdp column
co2 = co2.drop(columns='gdp')

#removing any incomplete data
co2 = co2.query(" gdp_per_capita>0 & co2_per_capita>0")
co2.dropna().sample(5)
country year population co2_per_capita consumption_co2_per_capita gdp_per_capita
614 Burkina Faso 2015 18718022.0 0.198 0.260 1401.644279
2089 Kyrgyzstan 2002 5026646.0 0.979 1.118 3216.956624
2751 Nigeria 2013 174726128.0 0.666 0.645 5493.963030
1663 Hong Kong 2010 7132437.0 5.617 11.312 41909.730236
3942 United Arab Emirates 2015 8916909.0 24.266 27.123 77553.611172

I would like to make graphic where I can colored a country based on its continent, just for an additional context to the data. We took that from Gapminder dataset1, and combine it with the previously curated CO2 dataset we just created.

Show Code
#importing gapminder
gapminder=pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
gapminder = gapminder[['country', 'continent']]
gapminder = gapminder.drop_duplicates().reset_index(drop=True)

#merging with original co2 dataset
co2 = pd.merge(co2, gapminder, on='country', how='inner')

#drop consumption per capita
co2 = co2.drop(columns='consumption_co2_per_capita')

#sanity check
co2
country year population co2_per_capita gdp_per_capita continent
0 Albania 1990 3295073.0 1.675 3929.457471 Europe
1 Albania 1991 3302087.0 1.299 2839.369269 Europe
2 Albania 1992 3303738.0 0.762 2647.207768 Europe
3 Albania 1993 3300715.0 0.708 2919.476286 Europe
4 Albania 1994 3294001.0 0.584 3216.795546 Europe
... ... ... ... ... ... ...
2786 Zimbabwe 2014 13855758.0 0.862 1531.673864 Africa
2787 Zimbabwe 2015 14154937.0 0.866 1485.520916 Africa
2788 Zimbabwe 2016 14452705.0 0.729 1450.371681 Africa
2789 Zimbabwe 2017 14751101.0 0.651 1487.877848 Africa
2790 Zimbabwe 2018 15052191.0 0.784 1509.106089 Africa

2791 rows × 6 columns


I would like to also see depending on the GDP per Capita, from which income class is a certain country belongs to. I am using a rough classification by world-bank. I know this may not be the best representation as income class is not the same every year2, and I am not exactly using exact number here, but I think this is good enough to put some contexts for data illustration.

Show Code
#creating income class category based on gdp per capita. 

bins= [0.00001,1000,4000,12000,1000000] #setting up the group based on bmi bins 
labels = [
         'lower',
         'lower-middle',
         'upper-middle',
         'upper'
         ] #setting up the label on each group

co2['income_class']= pd.cut(
   co2['gdp_per_capita'], 
   bins=bins, 
   labels=labels,
   include_lowest=False
   )

co2
country year population co2_per_capita gdp_per_capita continent income_class
0 Albania 1990 3295073.0 1.675 3929.457471 Europe lower-middle
1 Albania 1991 3302087.0 1.299 2839.369269 Europe lower-middle
2 Albania 1992 3303738.0 0.762 2647.207768 Europe lower-middle
3 Albania 1993 3300715.0 0.708 2919.476286 Europe lower-middle
4 Albania 1994 3294001.0 0.584 3216.795546 Europe lower-middle
... ... ... ... ... ... ... ...
2786 Zimbabwe 2014 13855758.0 0.862 1531.673864 Africa lower-middle
2787 Zimbabwe 2015 14154937.0 0.866 1485.520916 Africa lower-middle
2788 Zimbabwe 2016 14452705.0 0.729 1450.371681 Africa lower-middle
2789 Zimbabwe 2017 14751101.0 0.651 1487.877848 Africa lower-middle
2790 Zimbabwe 2018 15052191.0 0.784 1509.106089 Africa lower-middle

2791 rows × 7 columns

Data Exploration and Illustration

The first exploration of the data is to see how much change every country experiencing with over the course of 28 years from 1990-2018, and how the relationship between CO2 emission per Capita vs GDP per Capita look like.

Figure 4 shows the time-lapse between years, annotated to some countries from low (e.g. Ethiopia, Bangladesh), middle (e.g. Indonesia, India) to high (Singapore, USA, UK, etc.) GDP per CO2 Ratio.

The position is relatively stable especially for high-income countries like US, UK, and Germany, but drastic change for low-middle income countries.

Show Code
import plotly_express as px

source = co2

#selected countries to annotate
highlighted_countries = ['United States', 'Germany', 'United Kingdom',
                         'China', 'Singapore','Mexico', 'India', 'Indonesia', 
                         'Nigeria', 'Vietnam', 'Bangladesh', 'Ethiopia'
                        ]

# Create a new column for text values based on the condition
source['text_value'] = source['country'].apply(lambda country: country if country in highlighted_countries else '')

fig = px.scatter(data_frame=source, 
           x="co2_per_capita", 
           y="gdp_per_capita", 
           animation_frame="year", 
           animation_group="country",
           size="population", 
           color="continent", 
           hover_name="country", 
           log_x = True, log_y=True,
           size_max=80,
           width=700,
           height=800,
           # text_baseline='bottom',
           range_x=[0.01,100], 
           range_y=[400,90000],
           text='text_value'
          )


fig.update_layout(
    # title='CO2 Emission vs GDP of Countries',
    xaxis_title='CO2 Emission per Capita (tonnes)',
    yaxis_title='GDP per Capita (USD)',
    legend=dict(
    orientation="h",
    yanchor="bottom",
    y=1.02,
    xanchor="right",
    x=1
)
)

fig.show()
Figure 4: 1990-2018 Time-lapse Chart of CO2 Emission and GDP per Country

Country with Decreased CO2 Emission & Increased GDP

If we recall some articles from OWID, where they pointed out some countries such as United Kingdom, where the economic growth still happening while at the same time, reducing the CO2 emission as shown in Figure 1. It sounds impressive, but from the Figure 5 below, it is quite clear on why some countries like United Kingdom, Germany or USA were able to decoupled their economy from their CO2 emissions.

Because they are already rich.

It is easy to ignore the fact that those countries were sitting on top of other countries in terms of income level, with GDP per Capita at the high-income class countries, consistently above 20,000 USD ever since 1990.

The narrative that a country can really keep increasing their GDP per Capita without producing more CO2 emission is really an oversimplification of the whole set of conditions that allow a country to do so.

Show Code
import altair as alt

highlighted_countries = ['India', 'Indonesia', 'United Kingdom', 'Germany', 'United States']

source=co2[co2['country'].isin(highlighted_countries)]

alt.Chart(
    source,
    title=alt.Title(
        "GDP per Capita vs CO2 Emission",
        subtitle=["Different CO2 vs GDP rate in different Countries"],
        anchor='middle',
        offset=10, fontSize=16, 
    )
    ).mark_point(size=90, filled=True, opacity=0.7).encode(
    x=alt.X(
        'co2_per_capita:Q', title='CO2 per Capita',
        scale=alt.Scale(type="log", domain=[0.3, 30])
        ),
    y=alt.Y(
        'gdp_per_capita:Q', title='GDP per Capita',
        scale=alt.Scale(type="log")
        ),
    color=alt.Color('year', title='Year'),
    shape=alt.Shape('country', title='Country'),
    tooltip=['country', 'population', 'co2_per_capita', 'gdp_per_capita', 'year']
).properties(
    width='container',
    height=400,
).interactive()
Figure 5: CO2 vs GDP per Capita for some countries with different trend

A country needs to be rich first, at around 20,000 USD GDP per Capita before they can decouple their CO2 emission from GDP. To be rich, a country will have to use more energy, and likely to produce more CO2 emissions because of that. Even using a modest estimation of 5% GDP growth, and 2% inflation rate, it will take 7 years, before Indonesia can reach 20,000 USD per Capita level.

Another view is to see if there is country where the CO2 emission is reduced, but at the same time, their economy halted, and their GDP per Capite is reduced as well. To do that, let’s create a new sets of columns, of the difference in GDP per Capita per country.

Show Code
# create a column for gdp changes between 1990-2018

# Pivot the DataFrame to have years as columns
gdp_df = co2.pivot(index='country', columns='year', values='gdp_per_capita')
# pivoted_df

# Calculate the difference between GDP values for years 1980 and 2018
gdp_df['gdp_diff'] = gdp_df[2018] - gdp_df[1990]

# Reset the index to convert the DataFrame back to the original format
gdp_df.reset_index(inplace=True)

# Merge the calculated difference back to the original DataFrame
merged_df = pd.merge(co2, gdp_df[['country', 'gdp_diff']], on='country', how='left')

merged_df
country year population co2_per_capita gdp_per_capita continent income_class text_value gdp_diff
0 Albania 1990 3295073.0 1.675 3929.457471 Europe lower-middle 7891.497683
1 Albania 1991 3302087.0 1.299 2839.369269 Europe lower-middle 7891.497683
2 Albania 1992 3303738.0 0.762 2647.207768 Europe lower-middle 7891.497683
3 Albania 1993 3300715.0 0.708 2919.476286 Europe lower-middle 7891.497683
4 Albania 1994 3294001.0 0.584 3216.795546 Europe lower-middle 7891.497683
... ... ... ... ... ... ... ... ... ...
2786 Zimbabwe 2014 13855758.0 0.862 1531.673864 Africa lower-middle -659.894783
2787 Zimbabwe 2015 14154937.0 0.866 1485.520916 Africa lower-middle -659.894783
2788 Zimbabwe 2016 14452705.0 0.729 1450.371681 Africa lower-middle -659.894783
2789 Zimbabwe 2017 14751101.0 0.651 1487.877848 Africa lower-middle -659.894783
2790 Zimbabwe 2018 15052191.0 0.784 1509.106089 Africa lower-middle -659.894783

2791 rows × 9 columns


Do the same for CO2 Emissions between 1990-2018.

Show Code
# create a column for co2 changes between 1990-2018

# Pivot the DataFrame to have years as columns
co2_df = co2.pivot(index='country', columns='year', values='co2_per_capita')
# pivoted_df

# Calculate the difference between GDP values for years 1980 and 2018
co2_df['co2_diff'] = co2_df[2018] - co2_df[1990]

# Reset the index to convert the DataFrame back to the original format
co2_df.reset_index(inplace=True)

# Merge the calculated difference back to the original DataFrame
merged_df = pd.merge(merged_df, co2_df[['country', 'co2_diff']], on='country', how='left')
merged_df
country year population co2_per_capita gdp_per_capita continent income_class text_value gdp_diff co2_diff
0 Albania 1990 3295073.0 1.675 3929.457471 Europe lower-middle 7891.497683 0.057
1 Albania 1991 3302087.0 1.299 2839.369269 Europe lower-middle 7891.497683 0.057
2 Albania 1992 3303738.0 0.762 2647.207768 Europe lower-middle 7891.497683 0.057
3 Albania 1993 3300715.0 0.708 2919.476286 Europe lower-middle 7891.497683 0.057
4 Albania 1994 3294001.0 0.584 3216.795546 Europe lower-middle 7891.497683 0.057
... ... ... ... ... ... ... ... ... ... ...
2786 Zimbabwe 2014 13855758.0 0.862 1531.673864 Africa lower-middle -659.894783 -0.754
2787 Zimbabwe 2015 14154937.0 0.866 1485.520916 Africa lower-middle -659.894783 -0.754
2788 Zimbabwe 2016 14452705.0 0.729 1450.371681 Africa lower-middle -659.894783 -0.754
2789 Zimbabwe 2017 14751101.0 0.651 1487.877848 Africa lower-middle -659.894783 -0.754
2790 Zimbabwe 2018 15052191.0 0.784 1509.106089 Africa lower-middle -659.894783 -0.754

2791 rows × 10 columns


With this new dataset, we can confirm our exploratory analysis before, what countries that can decoupled their CO2emission from economic growth (GDP)?

Figure 6 shows a distribution of countries where the their GDP per Capita increases between 1990-2018, while their CO2 emissions were decreased. One interesting fact is all countries were sitting above upper-middle income class at around 4,500 USD GDP per Capita, and some are still on the increasing trend (GDP and CO2 emission increase) for the past 10 years e.g. Columbia.

As shown, not every country created equally, as different country has different tipping point when they started to be on decreasing trend on CO2 emission while still increasing their GDP per Capita.

Show Code
import altair as alt

#country with increase gdp, but decreased co2
source=merged_df.query(" gdp_diff>0 & co2_diff<0 & population >= 2_000_000")

alt.Chart(
    source,
    title=alt.Title(
        "GDP per Capita vs CO2 Emission for Countries",
        subtitle=["Countries with minimum 2 Million population,", 
                  "increased GDP and reduced CO2 Emissions"],
        fontSize=16, offset=10
    )
    ).mark_point(size=90, filled=True, opacity=0.6).encode(
    x=alt.X(
        'co2_per_capita:Q', title='CO2 per Capita',
        scale=alt.Scale(type="log", domain=[0.5,50])
        ),
    y=alt.Y(
        'gdp_per_capita:Q', title='GDP per Capita',
        scale=alt.Scale(type="log")
        ),
    color=alt.Color('country', title='Country'),
    size=alt.Size('year:O', scale=alt.Scale(domain=[1990,1995,2000,2005,2010,2015,2020]), title='Year'),
    tooltip=['country', 'population', 'co2_per_capita', 'gdp_per_capita', 'year']
).properties(
    width='container',
    height=400,
).interactive()
Figure 6: Countries with low CO2 Emission and increase GDP (countries with minimum 2 Million population)

Country with Decreased CO2 Emission & Decreased GDP

This is part where we should expect some of the poorest country in the world, where their CO2 emission should not be halted because it is directly related to the their economic growth. Figure 8 shows country with worse condition in 2018 than they are in 1990, Zimbabwe. This country needs help, and if that means emitting more CO2 emission, so be it. In fact their carbon budget is still below their fair share, as shown in Figure 7, a night and day difference compared to UK carbon share3.

Figure 7: Cumulative emission on UK and Zimbabwe compared to their respective Carbon Budget (Fanning and Hickel 2023)
Show Code
import altair as alt

#country with decreased CO2 and GDP
source=merged_df.query(" gdp_diff<0 & co2_diff<0 ")

alt.Chart(
    source,
    title=alt.Title(
        "GDP per Capita vs CO2 Emission for Countries",
        subtitle=["Countries with decreased GDP and CO2 Emission"],
        fontSize=16, offset=10
    )
    ).mark_point(size=90, filled=True, opacity=0.6).encode(
    x=alt.X(
        'co2_per_capita:Q', title='CO2 per Capita',
        scale=alt.Scale(type="log", domain=[0.5,50])
        ),
    y=alt.Y(
        'gdp_per_capita:Q', title='GDP per Capita',
        scale=alt.Scale(type="log")
        ),
    color=alt.Color('country', title='Country'),
    size=alt.Size('year:O', scale=alt.Scale(domain=[1990,1995,2000,2005,2010,2015,2020]), title='Year'),
    tooltip=['country', 'population', 'co2_per_capita', 'gdp_per_capita', 'year']
).properties(
    width='container',
    height=400,
).interactive()
Figure 8: Countries with low CO2 Emission and low GDP

Country with Increased CO2 Emission & Increased GDP

This is probably the category where everyone is trying to judge on, country that is trying to grow their economy and in doing so- increase their CO2 emission. As shown inf Figure 9, these countries are all on the increasing trend, their GDP per Capita is increasing but at the same time they were emitting CO2, which is understandable.

Show Code
import altair as alt

#country with increased CO2 and GDP
source=merged_df.query(" gdp_diff>0 & co2_diff>0 ")

alt.Chart(
    source,
    title=alt.Title(
        "GDP per Capita vs CO2 Emission for Countries",
        subtitle=["Countries with Increased GDP and CO2 Emission"],
        fontSize=16, offset=10
    )
    ).mark_point(size=90, filled=True, opacity=0.6).encode(
    x=alt.X(
        'co2_per_capita:Q', title='CO2 per Capita',
        scale=alt.Scale(type="log",)
        ),
    y=alt.Y(
        'gdp_per_capita:Q', title='GDP per Capita',
        scale=alt.Scale(type="log")
        ),
    color=alt.Color('country', title='Country'),
    size=alt.Size('year:O', scale=alt.Scale(domain=[1990,1995,2000,2005,2010,2015,2020]), title='Year'),
    tooltip=['country', 'population', 'co2_per_capita', 'gdp_per_capita', 'year']
).properties(
    width='container',
    height=500,
).interactive()