#!/usr/bin/env python # coding: utf-8 # # Storytelling Data Visualization on Exchange Rates # ## Introduction # This project focus on the explanatory data visualization of the exchange rate between the euro (€) and the United State dollar (USD). # # In the case of the EURO-USD exchange rate, the higher the rate, the stronger the value of the euro, and *vice versa*. For example, the euro is weaker at the exchange rate of 0.83 in comparison to 1.60, as one pays 1 EURO to get 0.83 USD instead of 1.60 USD. # # We use a dataset of euro daily exchange rates from 1999 to January 2021, which was compiled and published by Daria Chemkaeva on [Kaggle](https://www.kaggle.com/lsind18/euro-exchange-daily-rates-19992020). The data was originally from the European Central Bank. # ### The Goal of the Project # # This project aims to illustrate the evolution of the EURO-USD exchange rate from 1999 to 2021 via storytelling data visualisation. # ### Summary of Results # EURO-USD exchange rate bottomed between 2000-2001 (during the 2000s recession) and peaked in 2008 (during the financial crisis). # # The Euro currency has been weak from 2015 until January 2021 due to multiple reasons, such as European Central Bank's quantitative easing programme, deepening of European sovereign debt crisis, the likelihood of an increase in US interest rates, 2019 global economic slowdown and Covid-19 recession. # --- # ## Exploring the Data # We set up the environment by importing the necessary libraries: # In[1]: import pandas as pd import matplotlib.pyplot as plt # Run the necessary Jupyter magic so that plots are displayed inline get_ipython().run_line_magic('matplotlib', 'inline') import matplotlib.style as style pd.plotting.register_matplotlib_converters() # Let's read the `euro-daily-hist_1999_2020.csv` dataset into DataFrame and store the dataset into the `exchange_rates` variable. # In[2]: exchange_rates = pd.read_csv('euro-daily-hist_1999_2020.csv') # We study the structure of the dataset by examining the first and last five rows. # In[3]: exchange_rates.head() # In[4]: exchange_rates.tail() # We further inspect the information by using `DataFrame.info()`. # In[5]: exchange_rates.info() # There are _5699 rows and 41 columns_ in this dataset. This dataset is composed of `float` (3) and `object` (38). # # We noticed that there are some _null values_ in this dataset. # In[6]: exchange_rates.isnull().values.any() # We dive further to investigate the total sum of missing values of each column, except the `Period\Unit:` column. This is because we already knew from the previous inspection that the `Period\Unit:` column does not have any null value and we want to focus on the column with currency. # In[7]: # Excluding the `Period\Unit:` column exchange_rates_currency_only = exchange_rates.iloc[:, 1:] # Get the sum of null values of each column exchange_rates_currency_only.isnull().sum() # There are 28,767 null values in total. Our currency of interest — the US dollar — does not have any null value. # In[8]: exchange_rates_currency_only.isnull().sum().sum() # --- # ## Data Cleaning # # Let's clean the data before we create data visualizations. # ### Renaming Columns # # First, we simplify and rename the `Period\Unit:` to `Time` and `[US dollar]` to `US_dollar`. Since we focus on the US dollar in this project, we do not rename other currency names. # In[9]: exchange_rates.rename(columns={'[US dollar ]':'US_dollar', 'Period\\Unit:':'Time'}, inplace=True) # Display the column names list(exchange_rates.columns) # ### Converting the `Time` Column to `datetime` Data Type # # Next, we convert the `Time` column to `datetime` data type. # In[10]: exchange_rates['Time'] = pd.to_datetime(exchange_rates['Time']) # In[11]: print(exchange_rates['Time'].dtype) # Then, we sort the `Time` values in ascending order and reset the index. # In[12]: exchange_rates.sort_values('Time', inplace=True) # In[13]: exchange_rates.reset_index(drop=True, inplace=True) # In[14]: exchange_rates.head() # In[15]: exchange_rates.tail() # ### Isolating the `Time` and the `US_dollar` Columns # # We isolate the `Time` and the `US_dollar` columns and assign them to the `euro_to_dollar` variable. # In[16]: euro_to_dollar = exchange_rates[['Time', 'US_dollar']].copy() # In[17]: euro_to_dollar.head() # In[18]: euro_to_dollar.tail() # In[19]: euro_to_dollar.info() # ### Removing Non-numeric Values # # We inspected the values of `US_dollar` and found 62 entries of `-`, which are not numeric values. # In[20]: euro_to_dollar['US_dollar'].value_counts() # In[21]: dash_symbol_before = euro_to_dollar[euro_to_dollar['US_dollar'] == '-'] print('The amount of "-": ', dash_symbol_before.shape[0]) # `-` does not makes sense for our data analysis and visualisation. Therefore, we need to remove the rows with `-`. # In[22]: # euro_to_dollar = euro_to_dollar[euro_to_dollar != '-'] euro_to_dollar = euro_to_dollar[euro_to_dollar['US_dollar'] != '-'] # In[23]: dash_symbol_after = euro_to_dollar[euro_to_dollar['US_dollar'] == '-'] print('The amount of "-": ', dash_symbol_after.shape[0]) # Since the original data type of `US_dollar` is `object`, we convert it to `float` for data analysis and visualization. # In[24]: # Convert the data type of `US_dollar` to `float` euro_to_dollar['US_dollar'] = euro_to_dollar['US_dollar'].astype(float) # In[25]: # Examine whether the data type of `US_dollar` has been converted to `float` euro_to_dollar.info() # --- # ## Generating a Line Plot by Using Rolling Mean # # After data cleaning, we visualise the change of the euro-dollar exchange rate over time by using a line plot. # In[26]: plt.plot(euro_to_dollar['Time'], euro_to_dollar['US_dollar']) plt.show() # We observe many tiny fluctuations at the line of our line plot, which is due to the daily variation in the exchange rate. Since we are more interested in the long-term trend of the exchange rate, we will use a _rolling mean_ with a _rolling window of 30 days_ to generate the line plot. # # To do this, we compute the rolling mean and assign it to a new column named `rolling_mean`. # In[27]: euro_to_dollar['rolling_mean'] = euro_to_dollar['US_dollar'].rolling(30).mean() # In[28]: euro_to_dollar.head() # In[29]: euro_to_dollar.tail() # Now, let's generate a smoother line plot with a rolling window of 30 days. # In[30]: plt.plot(euro_to_dollar['Time'], euro_to_dollar['rolling_mean']) plt.show() # --- # ## Isolating the Lowest and Highest Exchange Rate per Year # # To get the lowest and the highest exchange rate along the evolution of the EURO-USD exchange rate, we do the following: # - We isolate the *years* from `Time` and assign them to a new column named `Year`. # - We use `df.pivot_table()` to compute the *minimum and maximum exchange rate per year*. # In[31]: # Isolating years and assign it to a new column named `Year` euro_to_dollar['Year'] = euro_to_dollar['Time'].dt.year euro_to_dollar.head() # In[32]: import numpy as np # Checking for the minimum exchange rate for each year min_euro_to_dollar = euro_to_dollar.pivot_table(values='US_dollar', index='Year', aggfunc=np.min) min_euro_to_dollar # In[33]: # Checking for the maximum exchange rate for each year max_euro_to_dollar = euro_to_dollar.pivot_table(values='US_dollar', index='Year', aggfunc=np.max) max_euro_to_dollar # --- # ## The Evolution of EURO-USD Exchange Rate: Events Highlights # # We highlight some events/crises that impacted on the EURO-USD exchange rate from 1999 to 2021 and visualise them on a line plot with *ggplot* Matplotlib style. # In[34]: # Isolating the `years` of the early 2000s recession (2000 - 2002) early2000s_recessions = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2000) & (euro_to_dollar['Time'].dt.year < 2003)] # Isolating the `years` of the financial crisis (2007 - 2009) financial_crisis = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2007) & (euro_to_dollar['Time'].dt.year < 2010)] # Isolating the `years` of the European sovereign debt crisis (2015 - 2017) eu_debt_crisis = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2015) & (euro_to_dollar['Time'].dt.year < 2018)] # Isolating the `years` of the 2019 global economic slowdown # and Covid-19 recession (2019 - 2020) economic_slowdown_Covid = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2019) & (euro_to_dollar['Time'].dt.year < 2021)] # In[35]: # Adding Matplotlib style style.use('ggplot') # Creating a line plot fig, ax = plt.subplots(figsize=(12,6)) ax.plot(euro_to_dollar['Time'], euro_to_dollar['rolling_mean'], linewidth=1, color='grey') # Setting the facecolor of the axis to white ax.set_facecolor(color='#ffffff') # Changing the color of grid to a lighter color ax.grid(color='#f0f0f0') # Hiding ticks ax.tick_params(bottom=False, left=False) # Setting the y limit ax.set_ylim(0.8, 1.9) # Reducing the y ticks ax.set_yticks([0.8, 1.0, 1.2, 1.4, 1.6]) # Setting tick label color ax.tick_params(colors='#9E9E9E', which='both') # ---------------------------------------------------------------------------- # Highlighting the period of global economy crisis events = [early2000s_recessions, financial_crisis, eu_debt_crisis, economic_slowdown_Covid] for e in events: start_year = e['Time'].min() end_year = e['Time'].max() ax.axvspan(xmin=start_year, xmax=end_year, ymin=0, ymax=1, alpha=0.12, color='grey') # ---------------------------------------------------------------------------- # Highlighting the line of the early 2000s recession (2000 - 2002) ax.plot(early2000s_recessions['Time'], early2000s_recessions['rolling_mean'], linewidth=2.5, color='#9450B3') # Highlighting the line of the financial crisis (2007 - 2009) ax.plot(financial_crisis['Time'], financial_crisis['rolling_mean'], linewidth=2.5, color='#9450B3') # Highlighting the line of the European sovereign debt crisis (2015 - 2017) ax.plot(eu_debt_crisis['Time'], eu_debt_crisis['rolling_mean'], linewidth=2.5, color='#9450B3') # Highlighting the line of the global economic slowdown and Covid-19 recession (2019 - 2020) ax.plot(economic_slowdown_Covid['Time'], economic_slowdown_Covid['rolling_mean'], linewidth=2.5, color='#9450B3') # ---------------------------------------------------------------------------- # Adding crisis descriptions # Adding the `Early 2000s Recession` ax.text(x=730280, y=1.82, s='Early 2000s', color='#424242', size=10) ax.text(x=730280, y=1.77, s='Recession', color='#424242', size=10) # Adding the `Financial Crisis` ax.text(x=732930, y=1.82, s='Financial', color='#424242', size=10) ax.text(x=732930, y=1.77, s='Crisis', color='#424242', size=10) # Adding the `European Sovereign Debt Crisis` ax.text(x=735770, y=1.82, s='European', color='#424242', size=10) ax.text(x=735770, y=1.77, s='Sovereign', color='#424242', size=10) ax.text(x=735770, y=1.72, s='Debt Crisis', color='#424242', size=10) # Adding the `2019 Global Economic Slowdown and Covid-19 Recession` ax.text(x=737100, y=1.82, s='Global', color='#424242', size=10) ax.text(x=737100, y=1.77, s='Economic', color='#424242', size=10) ax.text(x=737100, y=1.72, s='Slowdown', color='#424242', size=10) ax.text(x=737100, y=1.67, s='& Covid-19', color='#424242', size=10) ax.text(x=737100, y=1.62, s='Recession', color='#424242', size=10) # ---------------------------------------------------------------------------- # Adding title ax.text(x=729100, y=2.08, s='EURO-USD Rates are Bottomed Again Since 2015', size=18, weight='bold') # Adding subtitle ax.text(x=729100, y=2.00, s='EURO-USD Exchange Rates between 1999 to 2021', size=12) # Adding Signature Bar ax.text(x=729100, y=0.68, s='©SPWong' + ' '*146 + 'Source: European Central Bank', color='#ffffff', backgroundcolor='#424242', size=10) plt.show() # After the introduction of the euro currency in 1999, the EURO-USD exchange rate plummeted to its lowest point during the **early 2000s recession**. It hit the euro hardest **between 2000 and 2001**, with an exchange rate of 0.83 in 2000. The value of the euro appreciated rapidly starting from 2002. # # During the **financial crisis (2007-2009)**, the EURO-USD exchange rate rose to its record high at 1.60. Nonetheless, it dropped immensely to 1.25 before rising again to its historical second-highest rate, 1.51, at the end of the year 2009. # # **Between 2015 and 2017**, EURO-USD exchange rate plummeted rapidly due to multiple factors, such as **the European Central Bank's quantitative easing programme, the deepening of the Greek crisis and the likelihood of an increase in US interest rates** ([Source: The Guardian](https://www.theguardian.com/business/2015/mar/11/euro-12-year-low-gainst-the-dollar)). The EURO-USD rate dropped to its lowest at 1.04 in 2016. Since then, the value of the euro has not been able to recover to its good old time, i.e. between 2007 and 2014. # # The EURO-USD exchange rate suffered again **between 2019 and 2020**. The [major reasons](https://en.wikipedia.org/wiki/COVID-19_recession#2019_global_economic_slowdown) for the **2019 global economic slowdown** were due to Brexit, China-United States trade war and the potential liquidity crisis. The EURO-USD rate hit its lowest point at 1.07 in 2020, during the **Covid-19 recession**, the worst global economic recession caused by the Covid-19 pandemic. # ## The Evolution of the EURO-USD Exchange Rate Under the Last Three US Presidents # We are curious to investigate the evolution of EURO-USD exchange rate under the last three US presidents along with the impact of the historical events/crises. # # To do this, we need to group the data of each president based on their serving periods. The US presidents serving periods are as below: # - Bush: 2001-2009 # - Obama: 2009-2017 # - Trump: 2017-2021 # In[36]: bush = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2001) & (euro_to_dollar['Time'].dt.year < 2009)] obama = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2009) & (euro_to_dollar['Time'].dt.year < 2017)] trump = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2017) & (euro_to_dollar['Time'].dt.year < 2021)] # We compute the mean of `US_dollar`, 1.20, and use it as a guideline for our detailed analysis later. # In[37]: euro_to_dollar.mean() # Let's visualize the data by using line charts with *ggplot* Matplotlib style. # In[38]: # Adding Matplotlib style style.use('ggplot') # Adding a line plot plt.figure(figsize=(12,8)) ax1 = plt.subplot(2,3,1) ax2 = plt.subplot(2,3,2) ax3 = plt.subplot(2,3,3) ax4 = plt.subplot(2,1,2) axes = [ax1, ax2, ax3, ax4] # Adding spacing between subplots plt.tight_layout(w_pad=2.0, h_pad=7.0) # Setting the parameters for all plots for ax in axes: ax.set_facecolor(color='#ffffff') # Setting the facecolor of the axis to white ax.grid(color='#f0f0f0') # Changing the color of grid to a lighter color ax.tick_params(bottom=False, left=False) # Hiding ticks ax.set_yticks([0.8, 1.0, 1.2, 1.4, 1.6]) # Reducing the y ticks ax.set_ylim(0.8, 1.6) # Setting the y-axis view limits ax.tick_params(colors='#9E9E9E', which='both') # Setting tick label color # ---------------------------------------------------------------------------- # ax1: Bush ax1.plot(bush['Time'], bush['rolling_mean'], linewidth=2.5, color='blue') ax1.set_xticklabels(['', '2001', '', '2003', '', '2005', '', '2007', '', '2009']) # # Converting the start and end years (of the global economy crisis) to datetime # dt2001 = pd.to_datetime('2001') # dt2004 = pd.to_datetime('2004') # dt2007 = pd.to_datetime('2007') dt2009 = pd.to_datetime('2009') # # Highlighting the crisis period during Bush time # ax1.axvspan(xmin=dt2001, xmax=dt2004, ymin=0, ymax=0.986, # alpha=0.12, color='grey') # year 2001 - 2003 # ax1.axvspan(xmin=dt2007, xmax=dt2009, ymin=0, ymax=0.986, # alpha=0.12, color='grey') # year 2007 - 2008 # ---------------------------------------------------------------------------- # Highlighting the period of global economy crisis # events = [early2000s_recessions, financial_crisis, eu_debt_crisis, economic_slowdown_Covid] ev = [early2000s_recessions, financial_crisis] for i in ev: start_year = i['Time'].min() end_year = i['Time'].max() ax1.axvspan(xmin=start_year, xmax=end_year, ymin=0, ymax=1, alpha=0.12, color='grey') # ---------------------------------------------------------------------------- # Adding title ax1.text(x=731690, y=1.75, s='Bush',size=14, weight='bold', color='blue') # Adding subtitle ax1.text(x=731540, y=1.67, s='(2001-2009)', alpha=0.7) # ---------------------------------------------------------------------------- # ax2: Obama ax2.plot(obama['Time'], obama['rolling_mean'], linewidth=2.5, color='green') ax2.set_xticklabels(['', '2009', '', '2011', '', '2013', '', '2015', '', '2017']) # Converting the start and end years (of the global economy crisis) to datetime dt2010 = pd.to_datetime('2010') dt2015 = pd.to_datetime('2015') dt2017 = pd.to_datetime('2017') # Highlighting the crisis period during Obama time ax2.axvspan(xmin=dt2009, xmax=dt2010, ymin=0, ymax=0.986, alpha=0.12, color='grey') # year 2009 ax2.axvspan(xmin=dt2015, xmax=dt2017, ymin=0, ymax=0.986, alpha=0.12, color='grey') # year 2015 - 2016 # Adding title ax2.text(x=734500, y=1.75, s='Obama',size=14, weight='bold', color='green') # Adding subtitle ax2.text(x=734470, y=1.67, s='(2009-2017)', alpha=0.7) # ---------------------------------------------------------------------------- # ax3: Trump ax3.plot(trump['Time'], trump['rolling_mean'], linewidth=2.5, color='orange') ax3.set_xticklabels(['2017', '', '2018', '', '2019', '', '2020', '', '2021']) # Converting the start and end years (of the global economy crisis) to datetime dt2017 = pd.to_datetime('2017') dt2018 = pd.to_datetime('2018') dt2020 = pd.to_datetime('2020') dt2021 = pd.to_datetime('2021') dt2021 = pd.to_datetime('2021') # Highlighting the crisis period during Obama time ax3.axvspan(xmin=dt2017, xmax=dt2018, ymin=0, ymax=0.986, alpha=0.12, color='grey') # year 2017 ax3.axvspan(xmin=dt2020, xmax=dt2021, ymin=0, ymax=0.986, alpha=0.12, color='grey') # year 2020 # Adding title ax3.text(x=736910, y=1.75, s='Trump',size=14, weight='bold', color='orange') # Adding subtitle ax3.text(x=736860, y=1.67, s='(2017-2021)', alpha=0.7) # ---------------------------------------------------------------------------- # ax4: All together ax4.plot(euro_to_dollar['Time'], euro_to_dollar['rolling_mean'], linewidth=1, color='grey') ax4.plot(bush['Time'], bush['rolling_mean'], linewidth=2.5, color='blue') # Bush ax4.plot(obama['Time'], obama['rolling_mean'], linewidth=2.5, color='green') # Obama ax4.plot(trump['Time'], trump['rolling_mean'], linewidth=2.5, color='orange') # Trump # Highlighting the global economy crisis period for s, e in zip(start_year_dt, end_year_dt): ax.axvspan(xmin=s, xmax=e, ymin=0, ymax=0.986, alpha=0.12, color='grey') # Adding title ax4.text(x=731750, y=1.73, s='All Together with the Last Three US Presidents',size=14, weight='bold', color='Grey') # Adding subtitle ax4.text(x=733460, y=1.65, s='(1999-2021)', alpha=0.7) # ---------------------------------------------------------------------------- # For all plots, adding horizontal line for rolling mean from 1999 - 2021 for ax in axes: ax.axhline(xmin=0.008, xmax=0.99, y=1.20, color='grey', alpha=0.5) # Adding figure title ax1.text(x=729100, y=2.08, s='EURO-USD Rate Averaged 1.20 between 1999 - 2021',size=24, weight='bold') # Adding figure subtitle ax1.text(x=729100, y=2.00, s='EURO-USD Exchange Rates under US Presidents Bush, Obama and Trump', size=18) # Adding Signature Bar ax.text(x=729100, y=0.55, s='©SPWong' + ' '*200 + 'Source: European Central Bank', color='#ffffff', backgroundcolor='#757575', size=10) plt.show() # Based on the line plot, we observe that all the three US presidents share a similarity — the start and the end of their terms fall into the highlight of the major events/crises that influenced the EURO-USD exchange rate. # # By using the mean (1.2) of US dollars from 1999 to 2021 as a guideline, we made the following observations: # - **Bush**: Throughout Bush's presidency, the value of the US dollar against the euro **dropped significantly**. At the end of the Bush term, the value of the US dollar bottomed due to the financial crisis and the bursting of the US housing bubble. # - **Obama**: The value of the US dollar against the euro was **generally weak from 2009 to 2015**. in the last two years of Obama time, the US dollar against the euro became stronger — possibly due to the increase of US interest rates, the worsening of the Greece crisis, and the European Central Bank's quantitative easing programme. # - **Trump**: The EURO-USD exchange rate was **relatively stable** throughout Trump's term. The exchange rate below the mean guideline suggests that the value of the US dollar was generally robust. In the final months of Trump's presidency, the value of the US dollar decreased, possibly due to the worsening of the Covid-19 pandemic and recession. # ## Conclusion # # In this project, we study the evolution of the EURO-USD exchange rate from 1999-2021 by using a data visualisation approach. We found that ever since 2015, the EURO-USD exchange rate has been very weak — the second weakest period after the early 2000s recession. The impact of the financial crisis in 2008 seemed smaller on the EURO currency, instead it peaked in 2008.