This dataset describes Euro daily exchange rates between 1999 and 2021. The euro (symbolized with €) is the official currency in most of the countries of the European Union. If the exchange rate of the euro to the US dollar is 1.5, you get 1.5 US dollars if you pay 1.0 euro (one euro has more value than one US dollar at this exchange rate). Daria Chemkaeva put together the data set and made it available on Kaggle— the data source is the European Central Bank. Note that the dataset gets regular updates — we downloaded it on January 2021.
The aim of this project is to show the effect euro-dollar rate during the coronavirus pandemic, by using the 2020 data and the 2016-2019 data as a baseline.
#Import pandas and read in the data
import pandas as pd
exchange_rates = pd.read_csv('euro-daily-hist_1999_2020.csv')
#display first five rows
exchange_rates.head(5)
Period\Unit: | [Australian dollar ] | [Bulgarian lev ] | [Brazilian real ] | [Canadian dollar ] | [Swiss franc ] | [Chinese yuan renminbi ] | [Cypriot pound ] | [Czech koruna ] | [Danish krone ] | ... | [Romanian leu ] | [Russian rouble ] | [Swedish krona ] | [Singapore dollar ] | [Slovenian tolar ] | [Slovak koruna ] | [Thai baht ] | [Turkish lira ] | [US dollar ] | [South African rand ] | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2021-01-08 | 1.5758 | 1.9558 | 6.5748 | 1.5543 | 1.0827 | 7.9184 | NaN | 26.163 | 7.4369 | ... | 4.8708 | 90.8000 | 10.0510 | 1.6228 | NaN | NaN | 36.8480 | 9.0146 | 1.2250 | 18.7212 |
1 | 2021-01-07 | 1.5836 | 1.9558 | 6.5172 | 1.5601 | 1.0833 | 7.9392 | NaN | 26.147 | 7.4392 | ... | 4.8712 | 91.2000 | 10.0575 | 1.6253 | NaN | NaN | 36.8590 | 8.9987 | 1.2276 | 18.7919 |
2 | 2021-01-06 | 1.5824 | 1.9558 | 6.5119 | 1.5640 | 1.0821 | 7.9653 | NaN | 26.145 | 7.4393 | ... | 4.8720 | 90.8175 | 10.0653 | 1.6246 | NaN | NaN | 36.9210 | 9.0554 | 1.2338 | 18.5123 |
3 | 2021-01-05 | 1.5927 | 1.9558 | 6.5517 | 1.5651 | 1.0803 | 7.9315 | NaN | 26.227 | 7.4387 | ... | 4.8721 | 91.6715 | 10.0570 | 1.6180 | NaN | NaN | 36.7760 | 9.0694 | 1.2271 | 18.4194 |
4 | 2021-01-04 | 1.5928 | 1.9558 | 6.3241 | 1.5621 | 1.0811 | 7.9484 | NaN | 26.141 | 7.4379 | ... | 4.8713 | 90.3420 | 10.0895 | 1.6198 | NaN | NaN | 36.7280 | 9.0579 | 1.2296 | 17.9214 |
5 rows × 41 columns
#display last five rows
exchange_rates.tail(5)
Period\Unit: | [Australian dollar ] | [Bulgarian lev ] | [Brazilian real ] | [Canadian dollar ] | [Swiss franc ] | [Chinese yuan renminbi ] | [Cypriot pound ] | [Czech koruna ] | [Danish krone ] | ... | [Romanian leu ] | [Russian rouble ] | [Swedish krona ] | [Singapore dollar ] | [Slovenian tolar ] | [Slovak koruna ] | [Thai baht ] | [Turkish lira ] | [US dollar ] | [South African rand ] | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
5694 | 1999-01-08 | 1.8406 | NaN | NaN | 1.7643 | 1.6138 | NaN | 0.58187 | 34.938 | 7.4433 | ... | 1.3143 | 27.2075 | 9.1650 | 1.9537 | 188.8400 | 42.560 | 42.5590 | 0.3718 | 1.1659 | 6.7855 |
5695 | 1999-01-07 | 1.8474 | NaN | NaN | 1.7602 | 1.6165 | NaN | 0.58187 | 34.886 | 7.4431 | ... | 1.3092 | 26.9876 | 9.1800 | 1.9436 | 188.8000 | 42.765 | 42.1678 | 0.3701 | 1.1632 | 6.8283 |
5696 | 1999-01-06 | 1.8820 | NaN | NaN | 1.7711 | 1.6116 | NaN | 0.58200 | 34.850 | 7.4452 | ... | 1.3168 | 27.4315 | 9.3050 | 1.9699 | 188.7000 | 42.778 | 42.6949 | 0.3722 | 1.1743 | 6.7307 |
5697 | 1999-01-05 | 1.8944 | NaN | NaN | 1.7965 | 1.6123 | NaN | 0.58230 | 34.917 | 7.4495 | ... | 1.3168 | 26.5876 | 9.4025 | 1.9655 | 188.7750 | 42.848 | 42.5048 | 0.3728 | 1.1790 | 6.7975 |
5698 | 1999-01-04 | 1.9100 | NaN | NaN | 1.8004 | 1.6168 | NaN | 0.58231 | 35.107 | 7.4501 | ... | 1.3111 | 25.2875 | 9.4696 | 1.9554 | 189.0450 | 42.991 | 42.6799 | 0.3723 | 1.1789 | 6.9358 |
5 rows × 41 columns
exchange_rates.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 5699 entries, 0 to 5698 Data columns (total 41 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Period\Unit: 5699 non-null object 1 [Australian dollar ] 5699 non-null object 2 [Bulgarian lev ] 5297 non-null object 3 [Brazilian real ] 5431 non-null object 4 [Canadian dollar ] 5699 non-null object 5 [Swiss franc ] 5699 non-null object 6 [Chinese yuan renminbi ] 5431 non-null object 7 [Cypriot pound ] 2346 non-null object 8 [Czech koruna ] 5699 non-null object 9 [Danish krone ] 5699 non-null object 10 [Estonian kroon ] 3130 non-null object 11 [UK pound sterling ] 5699 non-null object 12 [Greek drachma ] 520 non-null object 13 [Hong Kong dollar ] 5699 non-null object 14 [Croatian kuna ] 5431 non-null object 15 [Hungarian forint ] 5699 non-null object 16 [Indonesian rupiah ] 5699 non-null object 17 [Israeli shekel ] 5431 non-null object 18 [Indian rupee ] 5431 non-null object 19 [Iceland krona ] 3292 non-null float64 20 [Japanese yen ] 5699 non-null object 21 [Korean won ] 5699 non-null object 22 [Lithuanian litas ] 4159 non-null object 23 [Latvian lats ] 3904 non-null object 24 [Maltese lira ] 2346 non-null object 25 [Mexican peso ] 5699 non-null object 26 [Malaysian ringgit ] 5699 non-null object 27 [Norwegian krone ] 5699 non-null object 28 [New Zealand dollar ] 5699 non-null object 29 [Philippine peso ] 5699 non-null object 30 [Polish zloty ] 5699 non-null object 31 [Romanian leu ] 5637 non-null float64 32 [Russian rouble ] 5699 non-null object 33 [Swedish krona ] 5699 non-null object 34 [Singapore dollar ] 5699 non-null object 35 [Slovenian tolar ] 2085 non-null object 36 [Slovak koruna ] 2608 non-null object 37 [Thai baht ] 5699 non-null object 38 [Turkish lira ] 5637 non-null float64 39 [US dollar ] 5699 non-null object 40 [South African rand ] 5699 non-null object dtypes: float64(3), object(38) memory usage: 1.8+ MB
In this dataset, there are a total of 41 columns and 5699 rows. Some of the rows have null values with a mixture of float and object data types.
#rename two columns in the dataframe
exchange_rates.rename({'Period\\Unit:':'Time', '[US dollar ]':'US_dollar'}, axis=1, inplace=True)
#change the Time column to a datetime data type
exchange_rates['Time'] = pd.to_datetime(exchange_rates['Time'])
#sort the values by Time column in ascending order
exchange_rates.sort_values('Time', inplace=True)
#reset the index and drop the initial index
exchange_rates.reset_index(drop=True, inplace=True)
euro_to_dollar = exchange_rates[['Time','US_dollar']]
euro_to_dollar
Time | US_dollar | |
---|---|---|
0 | 1999-01-04 | 1.1789 |
1 | 1999-01-05 | 1.1790 |
2 | 1999-01-06 | 1.1743 |
3 | 1999-01-07 | 1.1632 |
4 | 1999-01-08 | 1.1659 |
... | ... | ... |
5694 | 2021-01-04 | 1.2296 |
5695 | 2021-01-05 | 1.2271 |
5696 | 2021-01-06 | 1.2338 |
5697 | 2021-01-07 | 1.2276 |
5698 | 2021-01-08 | 1.2250 |
5699 rows × 2 columns
#check the counts of unique values in 'US_dollar' column
euro_to_dollar['US_dollar'].value_counts()
- 62 1.2276 9 1.1215 8 1.1305 7 1.0867 6 .. 1.0105 1 1.2897 1 0.8971 1 0.8417 1 1.1567 1 Name: US_dollar, Length: 3528, dtype: int64
#Drop all the rows where the '-' character appears in the US_dollar column
euro_to_dollar = euro_to_dollar[euro_to_dollar.US_dollar != '-']
#convert US_dollar column to a float data type
euro_to_dollar['US_dollar'] = euro_to_dollar['US_dollar'].astype(float)
euro_to_dollar.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 5637 entries, 0 to 5698 Data columns (total 2 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Time 5637 non-null datetime64[ns] 1 US_dollar 5637 non-null float64 dtypes: datetime64[ns](1), float64(1) memory usage: 132.1 KB
<ipython-input-8-7803d713fd49>:7: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy euro_to_dollar['US_dollar'] = euro_to_dollar['US_dollar'].astype(float)
#generate a line plot to visualize the evolution of the euro-dollar exchange rate
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(euro_to_dollar['Time'],
euro_to_dollar['US_dollar'])
plt.show()
plt.figure(figsize=(15,12))
plt.subplot(3, 2, 1)
plt.plot(euro_to_dollar['Time'],
euro_to_dollar['US_dollar'])
plt.title('Original values', weight='bold')
rolling = [7, 30, 50, 100, 365]
for i, rolls in zip(range(2,7), rolling):
plt.subplot(3, 2, i)
plt.plot(euro_to_dollar['Time'],
euro_to_dollar['US_dollar'].rolling(rolls).mean())
plt.title('Rolling Window:' + str(rolls), weight='bold')
plt.show()
euro_to_dollar['rolling_mean'] = euro_to_dollar['US_dollar'].rolling(30).mean()
<ipython-input-11-5ebbf27d070a>:1: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy euro_to_dollar['rolling_mean'] = euro_to_dollar['US_dollar'].rolling(30).mean()
We will show how the euro-dollar rate has changed during the coronavirus pandemic and show the 2020 data and the 2016-2019 data as a baseline.
coronadata_2020 = euro_to_dollar.copy()[euro_to_dollar['Time'].dt.year == 2020]
before_corona = euro_to_dollar.copy()[(euro_to_dollar['Time'].dt.year >= 2016) & (euro_to_dollar['Time'].dt.year <= 2019)]
### Adding the FiveThirtyEight style
import matplotlib.style as style
style.use('fivethirtyeight')
### Adding the subplots
plt.figure(figsize=(11, 6))
ax1 = plt.subplot(2,2,1)
ax2 = plt.subplot(2,2,2)
ax3 = plt.subplot(2,1,2)
axes = [ax1, ax2, ax3]
### Changes to all the subplots
for ax in axes:
ax.set_ylim(0.8, 1.6)
ax.set_yticks([1.0, 1.2, 1.4])
ax.set_yticklabels(['1.0', '1.2','1.4'],
alpha=0.3)
ax.grid(alpha=0.5)
### Ax1: Before corona 2016-2019
ax1.plot(before_corona['Time'], before_corona['rolling_mean'],
color='#0055ff')
ax1.set_xticklabels(['', '2016', '', '2017', '', '2018', '',
'2019'],
alpha=0.3)
ax1.text(16750, 1.8,'Pre-Coronavirus (2016-2019)', fontsize=18, weight='bold',
color='#0055ff')
### Ax2: corona 2020
ax2.plot(coronadata_2020['Time'], coronadata_2020['rolling_mean'],
color='#a00a4d')
ax2.set_xticklabels(['Q1-2020', '', 'Q2-2020', '', 'Q3-2020', '',
'Q4-2020'],
alpha=0.3)
ax2.text(18300, 1.8, 'Coronavirus (2020)', fontsize=18, weight='bold',
color='#a00a4d')
### Ax3: Merge both times
ax3.plot(before_corona['Time'], before_corona['rolling_mean'],
color='#0055ff')
ax3.plot(coronadata_2020['Time'], coronadata_2020['rolling_mean'],
color='#a00a4d')
ax3.grid(alpha=0.5)
ax3.set_xticks([])
### Adding a title and a subtitle
ax1.text(16350, 2.10, 'EURO-USD rate peaked at 1.24 and 1.21 before and after the Coronavirus Pandemic',
fontsize=20, weight='bold')
ax1.text(16350, 2.00, '''EURO-USD exchange rates in Pre-Coronavirus Era (2016-2018) and Coronavirus Era (2020)'''
,fontsize=16)
### Adding a signature
ax3.text(16500, 0.65, '©DATAQUEST' + ' '*140 + 'Source: European Central Bank',
color = '#f0f0f0', backgroundcolor = '#4d4d4d',
size=14)
plt.show()
<ipython-input-13-9bde7e13bd3f>:23: UserWarning: FixedFormatter should only be used together with FixedLocator ax1.set_xticklabels(['', '2016', '', '2017', '', '2018', '', <ipython-input-13-9bde7e13bd3f>:32: UserWarning: FixedFormatter should only be used together with FixedLocator ax2.set_xticklabels(['Q1-2020', '', 'Q2-2020', '', 'Q3-2020', '',
We built three graphs, two on the top row and one graph on the bottom row (where the two grids are merged). We did this to see how the effect the pandemic on the exchange rates from 2016 to 2020. From the plot, we can see that the exchange rate fluctuates,there was a mild rate decline in 2016 but it rises steadily mid 2017, where the rate is at an all time high but dips in 2018 and 2019. The decline is uniform until the end of q1 2020 where we see a steady movement upwards even till the end of Q4 2020. Overall, the exchange rates increased mostly in 2020, which may likely be due to the pandemic.