Climate Change Visual AnalysisΒΆ

ContextΒΆ

Climate change is a long-term change in the average weather patterns that have come to define Earth's local, regional and global climates. These changes have a broad range of observed effects that are synonymous with the term. This dataset provides an insight into the global temperature changes and the global CO2 emissions over the years.

ContentΒΆ

This dataset contains the following columns:

  • Year: The year in which the data was recorded
  • Mean global temperature: The mean global temperature recorded in that year
  • CO2 emissions: The CO2 emissions recorded in that year

ObjectiveΒΆ

To perform an exploratory data analysis on the dataset to understand the trends in the global temperature changes and CO2 emissions over the years.

ReferencesΒΆ

The dataset has been taken from Kaggle. The links to the dataset and other references are given below:

Raw Data:
Climate trends: https://ourworldindata.org/grapher/temperature-anomaly
CO2 trends: https://ourworldindata.org/co2-emissions#global-co2-emissions-from-fossil-fuels

x-limits:
Pre-industrial temperatures:
https://earthobservatory.nasa.gov/world-of-change/global-temperatures
https://unfccc.int/process-and-meetings/the-paris-agreement

y-limits:
https://www.europarl.europa.eu/infographic/climate-negotiations-timeline/index_en.html

shaded periods:
https://faculty.wcas.northwestern.edu/jmokyr/castronovo.pdf
https://www.anthroencyclopedia.com/entry/anthropocene#:~:text='The%20Anthropocene'%20is%20a%20term,bio%2Dgeophysical%20composition%20and%20processes.

callouts:
https://www.history.com/news/most-important-gilded-age-inventions
https://www.statista.com/statistics/1246890/vehicles-use-united-states-historical/
https://www.discover.ukri.org/a-brief-history-of-climate-change-discoveries/index.html#group-section-1990s-2000s-bwnXtJHqpd

Let's start by loading the dataset.

InΒ [1]:
import os
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from scipy.interpolate import make_interp_spline
from warnings import filterwarnings
filterwarnings("ignore")
InΒ [2]:
#reading in temperature data
temp_trends = pd.read_csv('temperature-anomaly.csv')

#reading in CO2 data
CO2_trends = pd.read_csv('annual-co2-emissions-per-country.csv')
InΒ [3]:
print(temp_trends.head())
print(temp_trends.describe())
   Entity  Code  Year  \
0  Global   NaN  1850   
1  Global   NaN  1851   
2  Global   NaN  1852   
3  Global   NaN  1853   
4  Global   NaN  1854   

   Global average temperature anomaly relative to 1961-1990  \
0                                          -0.417659          
1                                          -0.233350          
2                                          -0.229399          
3                                          -0.270354          
4                                          -0.291630          

   Upper bound of the annual temperature anomaly (95% confidence interval)  \
0                                          -0.246115                         
1                                          -0.054832                         
2                                          -0.049416                         
3                                          -0.110700                         
4                                          -0.150436                         

   Lower bound of the annual temperature anomaly (95% confidence interval)  
0                                          -0.589203                        
1                                          -0.411868                        
2                                          -0.409382                        
3                                          -0.430009                        
4                                          -0.432824                        
       Code         Year  \
count   0.0   522.000000   
mean    NaN  1936.500000   
std     NaN    50.276825   
min     NaN  1850.000000   
25%     NaN  1893.000000   
50%     NaN  1936.500000   
75%     NaN  1980.000000   
max     NaN  2023.000000   

       Global average temperature anomaly relative to 1961-1990  \
count                                         522.000000          
mean                                           -0.072792          
std                                             0.387320          
min                                            -0.701569          
25%                                            -0.354566          
50%                                            -0.193912          
75%                                             0.110119          
max                                             1.275727          

       Upper bound of the annual temperature anomaly (95% confidence interval)  \
count                                         522.000000                         
mean                                            0.038905                         
std                                             0.347909                         
min                                            -0.486698                         
25%                                            -0.199500                         
50%                                            -0.056851                         
75%                                             0.208315                         
max                                             1.333305                         

       Lower bound of the annual temperature anomaly (95% confidence interval)  
count                                         522.000000                        
mean                                           -0.184489                        
std                                             0.432559                        
min                                            -0.947684                        
25%                                            -0.521331                        
50%                                            -0.294819                        
75%                                             0.052181                        
max                                             1.236863                        
InΒ [4]:
#cleaning climate change data - restricted to world trends, removing rows with no temp anomoly data
climatechange_world = temp_trends[temp_trends['Entity']=='Global']

#filtering relevant columns
drop_cols = ['Entity','Code']
climatechange_world.drop(drop_cols,axis=1,inplace=True)

#renaming columns
rename_cols = {'Global average temperature anomaly relative to 1961-1990':'relative avg temp',
              'Upper bound of the annual temperature anomaly (95% confidence interval)':'upper bound',
              'Lower bound of the annual temperature anomaly (95% confidence interval)':'lower bound'}
climatechange_world.rename(columns=rename_cols,inplace=True)

#print df head
print(climatechange_world.head())
   Year  relative avg temp  upper bound  lower bound
0  1850          -0.417659    -0.246115    -0.589203
1  1851          -0.233350    -0.054832    -0.411868
2  1852          -0.229399    -0.049416    -0.409382
3  1853          -0.270354    -0.110700    -0.430009
4  1854          -0.291630    -0.150436    -0.432824
InΒ [5]:
print(CO2_trends[CO2_trends['Entity']=='World'].head())
print(CO2_trends[CO2_trends['Entity']=='World'].describe())
      Entity      Code  Year  Annual COβ‚‚ emissions
30814  World  OWID_WRL  1750             9350528.0
30815  World  OWID_WRL  1751             9350528.0
30816  World  OWID_WRL  1752             9354192.0
30817  World  OWID_WRL  1753             9354192.0
30818  World  OWID_WRL  1754             9357856.0
              Year  Annual COβ‚‚ emissions
count   272.000000          2.720000e+02
mean   1885.500000          6.385772e+09
std      78.663842          1.012492e+10
min    1750.000000          9.350528e+06
25%    1817.750000          4.959041e+07
50%    1885.500000          1.017573e+09
75%    1953.250000          6.683314e+09
max    2021.000000          3.712385e+10
InΒ [6]:
#cleaning CO2 data - restricted to world trends, only taking years greater than 1879
CO2_world = CO2_trends[(CO2_trends['Entity']=='World') & (CO2_trends['Year']>1849)]

#filtering relevant columns
drop_cols = ['Entity','Code']
CO2_world.drop(drop_cols,axis=1,inplace=True)

#print df head
print(CO2_world.head())
       Year  Annual COβ‚‚ emissions
30914  1850           196896030.0
30915  1851           198804980.0
30916  1852           207550940.0
30917  1853           217209250.0
30918  1854           255138980.0
InΒ [7]:
#merging dataframes
climate_data = pd.merge(climatechange_world,CO2_world,on='Year',how='inner')

#adding actual temperature (1961-1990 mean temperature of 14 degrees)
climate_data['avg temp'] = climate_data['relative avg temp']+14

#adding column to convert CO2 emissions to billions of tonnes
climate_data['COβ‚‚ emissions (billions of tonnes)'] = climate_data['Annual COβ‚‚ emissions']/1e9

#dropping all entries after 2021
climate_data = climate_data[climate_data['Year']<2022]

#dropping unused columns
drop_cols=['relative avg temp','upper bound','lower bound','Annual COβ‚‚ emissions']
climate_data.drop(drop_cols,axis=1,inplace=True)

print(climate_data.tail())
     Year   avg temp  COβ‚‚ emissions (billions of tonnes)
167  2017  14.845174                           36.096737
168  2018  14.762654                           36.826510
169  2019  14.891073                           37.082560
170  2020  14.922794                           35.264086
171  2021  14.761856                           37.123850
InΒ [8]:
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

Adding TrendlineΒΆ

InΒ [9]:
#Adding Anthropocene period
#https://www.discover.ukri.org/a-brief-history-of-climate-change-discoveries/index.html
#leading narrative - temperature & CO2 trends
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Spline for CO2 data
theta1 = np.polyfit(climate_data['Year'], 
                    climate_data['COβ‚‚ emissions (billions of tonnes)'],3)
CO2_spline = theta1[3]+theta1[2]*pow(climate_data['Year'],
                                     1)+theta1[1]*pow(climate_data['Year'],
                                                      2)+theta1[0]*pow(climate_data['Year'],3)

#plotting CO2 spline
ax1.plot(climate_data['Year'], CO2_spline,
         color='blue', linestyle ='dashed', linewidth=2, label=None)

# Spline for temp data
theta2 = np.polyfit(climate_data['Year'], 
                    climate_data['avg temp'],3)
temp_spline = theta2[3]+theta2[2]*pow(climate_data['Year'],
                                      1)+theta2[1]*pow(climate_data['Year'],
                                                       2)+theta2[0]*pow(climate_data['Year'],3)

#plotting temp spline
ax2.plot(climate_data['Year'], temp_spline,
         color='red', linestyle ='dashed', linewidth=2, label=None)

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

Adding x-limitsΒΆ

InΒ [10]:
#Adding Anthropocene period
#https://www.discover.ukri.org/a-brief-history-of-climate-change-discoveries/index.html
#leading narrative - temperature & CO2 trends
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Spline for CO2 data
theta1 = np.polyfit(climate_data['Year'], 
                    climate_data['COβ‚‚ emissions (billions of tonnes)'],3)
CO2_spline = theta1[3]+theta1[2]*pow(climate_data['Year'],
                                     1)+theta1[1]*pow(climate_data['Year'],
                                                      2)+theta1[0]*pow(climate_data['Year'],3)

#plotting CO2 spline
ax1.plot(climate_data['Year'], CO2_spline,
         color='blue', linestyle ='dashed', linewidth=2, label=None)

# Spline for temp data
theta2 = np.polyfit(climate_data['Year'], 
                    climate_data['avg temp'],3)
temp_spline = theta2[3]+theta2[2]*pow(climate_data['Year'],
                                      1)+theta2[1]*pow(climate_data['Year'],
                                                       2)+theta2[0]*pow(climate_data['Year'],3)

#plotting temp spline
ax2.plot(climate_data['Year'], temp_spline,
         color='red', linestyle ='dashed', linewidth=2, label=None)

#Constant lines
#setting constant line transparency
cnst_alpha=0.8

# Adding horizontal constant line at 14C (pre-industrial mean temp)
#https://earthobservatory.nasa.gov/world-of-change/global-temperatures
ax2.axhline(y=14, color='black', linestyle='--',alpha=cnst_alpha)
pre_ind_label = 'Pre-industrial Temperatures'
ax2.text(1882,14.03,pre_ind_label,color='black',alpha=cnst_alpha)

#Adding horizontal constant line at 15.5C (+1.5C Mean Temp)
ax2.axhline(y=15, color='darkgoldenrod', linestyle='--',alpha=cnst_alpha)
increase_label1 = '+1Β°C increase'
ax2.text(1882,15.03,increase_label1,color='darkgoldenrod',alpha=cnst_alpha)

# Adding horizontal constant line at 15C (+1C mean temp)
ax2.axhline(y=15.5, color='red', linestyle='--',alpha=cnst_alpha)
increase_label2 = '+1.5Β°C increase'
ax2.text(1882,15.53,increase_label2,color='red',alpha=cnst_alpha)

#Adding horizontal constant line at 16C (+2C Mean Temp)
ax2.axhline(y=16, color='darkred', linestyle='--',alpha=cnst_alpha)
increase_label3 = '+2Β°C increase'
ax2.text(1882,16.03,increase_label3,color='darkred',alpha=cnst_alpha)

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

Adding y-limitsΒΆ

InΒ [11]:
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Spline for CO2 data
theta1 = np.polyfit(climate_data['Year'], 
                    climate_data['COβ‚‚ emissions (billions of tonnes)'],3)
CO2_spline = theta1[3]+theta1[2]*pow(climate_data['Year'],
                                     1)+theta1[1]*pow(climate_data['Year'],
                                                      2)+theta1[0]*pow(climate_data['Year'],3)

#plotting CO2 spline
ax1.plot(climate_data['Year'], CO2_spline,
         color='blue', linestyle ='dashed', linewidth=2, label=None)

# Spline for temp data
theta2 = np.polyfit(climate_data['Year'], 
                    climate_data['avg temp'],3)
temp_spline = theta2[3]+theta2[2]*pow(climate_data['Year'],
                                      1)+theta2[1]*pow(climate_data['Year'],
                                                       2)+theta2[0]*pow(climate_data['Year'],3)

#plotting temp spline
ax2.plot(climate_data['Year'], temp_spline,
         color='red', linestyle ='dashed', linewidth=2, label=None)

#Constant lines
#setting constant line transparency
cnst_alpha=0.8

# Adding horizontal constant line at 14C (pre-industrial mean temp)
#https://earthobservatory.nasa.gov/world-of-change/global-temperatures
ax2.axhline(y=14, color='black', linestyle='--',alpha=cnst_alpha)
pre_ind_label = 'Pre-industrial Temperatures'
ax2.text(1882,14.03,pre_ind_label,color='black',alpha=cnst_alpha)

#Adding horizontal constant line at 15.5C (+1.5C Mean Temp)
ax2.axhline(y=15, color='darkgoldenrod', linestyle='--',alpha=cnst_alpha)
increase_label1 = '+1Β°C increase'
ax2.text(1882,15.03,increase_label1,color='darkgoldenrod',alpha=cnst_alpha)

# Adding horizontal constant line at 15C (+1C mean temp)
ax2.axhline(y=15.5, color='red', linestyle='--',alpha=cnst_alpha)
increase_label2 = '+1.5Β°C increase'
ax2.text(1882,15.53,increase_label2,color='red',alpha=cnst_alpha)

#Adding horizontal constant line at 16C (+2C Mean Temp)
ax2.axhline(y=16, color='darkred', linestyle='--',alpha=cnst_alpha)
increase_label3 = '+2Β°C increase'
ax2.text(1882,16.03,increase_label3,color='darkred',alpha=cnst_alpha)

#Adding vertical constant line at 1988 (IPCC)
plt.axvline(x=1988, color='darkgreen',linestyle='--',alpha=cnst_alpha)
IPCC_label='IPCC (1988)'
ax2.text(1986,13.5,IPCC_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 1995 (Kyoto)
plt.axvline(x=1997, color='darkgreen',linestyle='--',alpha=cnst_alpha)
kyoto_label='Kyoto (1997)'
ax2.text(1995,13.5,kyoto_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 2015 (Paris)
plt.axvline(x=2015, color='darkgreen',linestyle='--',alpha=cnst_alpha)
paris_label='Paris (2015)'
ax2.text(2013,13.5,paris_label,color='darkgreen',weight='bold', fontsize=10,rotation=90,alpha=cnst_alpha)

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

Adding shaded periodsΒΆ

InΒ [12]:
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Spline for CO2 data
theta1 = np.polyfit(climate_data['Year'], 
                    climate_data['COβ‚‚ emissions (billions of tonnes)'],3)
CO2_spline = theta1[3]+theta1[2]*pow(climate_data['Year'],
                                     1)+theta1[1]*pow(climate_data['Year'],
                                                      2)+theta1[0]*pow(climate_data['Year'],3)

#plotting CO2 spline
ax1.plot(climate_data['Year'], CO2_spline,
         color='blue', linestyle ='dashed', linewidth=2, label=None)

# Spline for temp data
theta2 = np.polyfit(climate_data['Year'], 
                    climate_data['avg temp'],3)
temp_spline = theta2[3]+theta2[2]*pow(climate_data['Year'],
                                      1)+theta2[1]*pow(climate_data['Year'],
                                                       2)+theta2[0]*pow(climate_data['Year'],3)

#plotting temp spline
ax2.plot(climate_data['Year'], temp_spline,
         color='red', linestyle ='dashed', linewidth=2, label=None)

#Constant lines
#setting constant line transparency
cnst_alpha=0.8

# Adding horizontal constant line at 14C (pre-industrial mean temp)
#https://earthobservatory.nasa.gov/world-of-change/global-temperatures
ax2.axhline(y=14, color='black', linestyle='--',alpha=cnst_alpha)
pre_ind_label = 'Pre-industrial Temperatures'
ax2.text(1882,14.03,pre_ind_label,color='black',alpha=cnst_alpha)

#Adding horizontal constant line at 15.5C (+1.5C Mean Temp)
ax2.axhline(y=15, color='darkgoldenrod', linestyle='--',alpha=cnst_alpha)
increase_label1 = '+1Β°C increase'
ax2.text(1882,15.03,increase_label1,color='darkgoldenrod',alpha=cnst_alpha)

# Adding horizontal constant line at 15C (+1C mean temp)
ax2.axhline(y=15.5, color='red', linestyle='--',alpha=cnst_alpha)
increase_label2 = '+1.5Β°C increase'
ax2.text(1882,15.53,increase_label2,color='red',alpha=cnst_alpha)

#Adding horizontal constant line at 16C (+2C Mean Temp)
ax2.axhline(y=16, color='darkred', linestyle='--',alpha=cnst_alpha)
increase_label3 = '+2Β°C increase'
ax2.text(1882,16.03,increase_label3,color='darkred',alpha=cnst_alpha)

#Adding vertical constant line at 1988 (IPCC)
plt.axvline(x=1988, color='darkgreen',linestyle='--',alpha=cnst_alpha)
IPCC_label='IPCC (1988)'
ax2.text(1986,13.5,IPCC_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 1995 (Kyoto)
plt.axvline(x=1997, color='darkgreen',linestyle='--',alpha=cnst_alpha)
kyoto_label='Kyoto (1997)'
ax2.text(1995,13.5,kyoto_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 2015 (Paris)
plt.axvline(x=2015, color='darkgreen',linestyle='--',alpha=cnst_alpha)
paris_label='Paris (2015)'
ax2.text(2013,13.5,paris_label,color='darkgreen',weight='bold', fontsize=10,rotation=90,alpha=cnst_alpha)

# Specifying regions to shade on the x-axis
plt.axvspan(1870, 1910, alpha=0.1, color='darkorange', 
            label='Second Industrial Revolution')
plt.axvspan(1945, 2022, alpha=0.1, color='royalblue', 
            label='The Anthropocene')

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

Adding calloutsΒΆ

InΒ [13]:
# Creating primary axis (CO2 emissions)
fig, ax1 = plt.subplots(figsize=(15, 9))
ax1.plot(climate_data['Year'], climate_data['COβ‚‚ emissions (billions of tonnes)'],
         color='steelblue',linewidth=2, label='CO2 emissions (billions of tonnes)')
ax1.set_xlabel('Year',weight='bold',fontsize=11)
ax1.set_ylabel('CO2 Emissions (Billions of Tonnes)',color='blue',weight='bold',fontsize=11)

# Adjusting gridlines on primary y-axis
ax1.grid(color='blue', linestyle='--', linewidth=0.5, alpha=0.3)

# Creating secondary y-axis (relative avg temp)
ax2 = ax1.twinx()
ax2.plot(climate_data['Year'], climate_data['avg temp'],
         color='salmon', linewidth=2, label='Average Temperature (Β°C)')
ax2.set_ylabel('Average Temperature (Β°C)',color='red',weight='bold',fontsize=11)

# Setting x-axis limits for ax
ax1.set_xlim(1850, 2022)

# Setting y-axis limits for both ax1 and ax2
ax1.set_ylim(0, 1.15 * max(climate_data['COβ‚‚ emissions (billions of tonnes)']))
ax2.set_ylim(0.999 * min(climate_data['avg temp']), 16.1)

# Spline for CO2 data
theta1 = np.polyfit(climate_data['Year'], 
                    climate_data['COβ‚‚ emissions (billions of tonnes)'],3)
CO2_spline = theta1[3]+theta1[2]*pow(climate_data['Year'],
                                     1)+theta1[1]*pow(climate_data['Year'],
                                                      2)+theta1[0]*pow(climate_data['Year'],3)

#plotting CO2 spline
ax1.plot(climate_data['Year'], CO2_spline,
         color='blue', linestyle ='dashed', linewidth=2, label=None)

# Spline for temp data
theta2 = np.polyfit(climate_data['Year'], 
                    climate_data['avg temp'],3)
temp_spline = theta2[3]+theta2[2]*pow(climate_data['Year'],
                                      1)+theta2[1]*pow(climate_data['Year'],
                                                       2)+theta2[0]*pow(climate_data['Year'],3)

#plotting temp spline
ax2.plot(climate_data['Year'], temp_spline,
         color='red', linestyle ='dashed', linewidth=2, label=None)

#Constant lines
#setting constant line transparency
cnst_alpha=0.8

# Adding horizontal constant line at 14C (pre-industrial mean temp)
#https://earthobservatory.nasa.gov/world-of-change/global-temperatures
ax2.axhline(y=14, color='black', linestyle='--',alpha=cnst_alpha)
pre_ind_label = 'Pre-industrial Temperatures'
ax2.text(1882,14.03,pre_ind_label,color='black',alpha=cnst_alpha)

#Adding horizontal constant line at 15.5C (+1.5C Mean Temp)
ax2.axhline(y=15, color='darkgoldenrod', linestyle='--',alpha=cnst_alpha)
increase_label1 = '+1Β°C increase'
ax2.text(1882,15.03,increase_label1,color='darkgoldenrod',alpha=cnst_alpha)

# Adding horizontal constant line at 15C (+1C mean temp)
ax2.axhline(y=15.5, color='red', linestyle='--',alpha=cnst_alpha)
increase_label2 = '+1.5Β°C increase'
ax2.text(1882,15.53,increase_label2,color='red',alpha=cnst_alpha)

#Adding horizontal constant line at 16C (+2C Mean Temp)
ax2.axhline(y=16, color='darkred', linestyle='--',alpha=cnst_alpha)
increase_label3 = '+2Β°C increase'
ax2.text(1882,16.03,increase_label3,color='darkred',alpha=cnst_alpha)

#Adding vertical constant line at 1988 (IPCC)
plt.axvline(x=1988, color='darkgreen',linestyle='--',alpha=cnst_alpha)
IPCC_label='IPCC (1988)'
ax2.text(1986,13.5,IPCC_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 1995 (Kyoto)
plt.axvline(x=1997, color='darkgreen',linestyle='--',alpha=cnst_alpha)
kyoto_label='Kyoto (1997)'
ax2.text(1995,13.5,kyoto_label,color='darkgreen',weight='bold',fontsize=10,rotation=90,alpha=cnst_alpha)

#Adding vertical constant line at 2015 (Paris)
plt.axvline(x=2015, color='darkgreen',linestyle='--',alpha=cnst_alpha)
paris_label='Paris (2015)'
ax2.text(2013,13.5,paris_label,color='darkgreen',weight='bold', fontsize=10,rotation=90,alpha=cnst_alpha)

# Specify the regions to shade on the x-axis
#https://www.nature.com/articles/d41586-019-01641-5
plt.axvspan(1870, 1910, alpha=0.1, color='darkorange', label='Second Industrial Revolution')
plt.axvspan(1945, 2022, alpha=0.1, color='royalblue', label='The Anthropocene')

# Combining legends for both axes
lines, labels = ax1.get_legend_handles_labels()
lines2, labels2 = ax2.get_legend_handles_labels()
ax2.legend(lines + lines2, labels + labels2, loc='upper right',fontsize=10)

#adding callouts for key dates
# Points to annotate (x, y, annotation_text)
callouts = [(1886, climate_data.loc[climate_data['Year'] == 1886, 'avg temp'].values[0], 'Automobile \ninvented'),
            (1903, climate_data.loc[climate_data['Year'] == 1903, 'avg temp'].values[0], 'Airplane \ninvented'),
            (1921, climate_data.loc[climate_data['Year'] == 1921, 'avg temp'].values[0], 'Automobiles in America\nexceed 10 million'),
            (1938, climate_data.loc[climate_data['Year'] == 1938, 'avg temp'].values[0], 'Rise in global\ntemperatures proven;\nOil discovered in\nSaudi Arabia'), 
            (1968, climate_data.loc[climate_data['Year'] == 1968, 'avg temp'].values[0], 'Melting ice caps \npredicted'), 
            (1985, climate_data.loc[climate_data['Year'] == 1985, 'avg temp'].values[0], 'Ozone hole \ndiscovered'),
            (1994, climate_data.loc[climate_data['Year'] == 1994, 'avg temp'].values[0], '1st climate change \ntreaty signed into law'),
            (2003, climate_data.loc[climate_data['Year'] == 2003, 'avg temp'].values[0], 'European heatwave \nkills 70,000+'),
            (2021, climate_data.loc[climate_data['Year'] == 2021, 'avg temp'].values[0], 'EU climate law\nratified')
           ]

# Iterate over specified points and add minimal annotations
for point in callouts:
    x_point, y_point, annotation_text = point
    ax2.annotate(annotation_text, xy=(x_point, y_point), xytext=(x_point - 35, y_point + 0.7),
                 arrowprops=dict(arrowstyle='-', color='black'),
                 fontsize=9, weight='bold')  # Set font size for annotation text
                 
# Set title
plt.title('Global CO2 Emissions compared to Average Global Temperature, 1850-2021',weight='bold',fontsize=14)

# Show plot
plt.show() 
No description has been provided for this image

SummaryΒΆ

As can be seen from the trendlines above, the global temperatures are increasing precipitously with a corresponding increase in CO2 emissions. By supplementing these graphics with additional callouts and shaded regions, we can add greater context to the problems faced and why they are occurring, and make more informed recommendations on what needs to be done in order to mitigate this damage.