import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from numpy import cov
import os
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
print(os.path.join(dirname, filename))
df=pd.read_csv('D://archive/african_crises.csv')
df
case | cc3 | country | year | systemic_crisis | exch_usd | domestic_debt_in_default | sovereign_external_debt_default | gdp_weighted_default | inflation_annual_cpi | independence | currency_crises | inflation_crises | banking_crisis | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | DZA | Algeria | 1870 | 1 | 0.052264 | 0 | 0 | 0.0 | 3.441456 | 0 | 0 | 0 | crisis |
1 | 1 | DZA | Algeria | 1871 | 0 | 0.052798 | 0 | 0 | 0.0 | 14.149140 | 0 | 0 | 0 | no_crisis |
2 | 1 | DZA | Algeria | 1872 | 0 | 0.052274 | 0 | 0 | 0.0 | -3.718593 | 0 | 0 | 0 | no_crisis |
3 | 1 | DZA | Algeria | 1873 | 0 | 0.051680 | 0 | 0 | 0.0 | 11.203897 | 0 | 0 | 0 | no_crisis |
4 | 1 | DZA | Algeria | 1874 | 0 | 0.051308 | 0 | 0 | 0.0 | -3.848561 | 0 | 0 | 0 | no_crisis |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
1054 | 70 | ZWE | Zimbabwe | 2009 | 1 | 354.800000 | 1 | 1 | 0.0 | -7.670000 | 1 | 1 | 0 | crisis |
1055 | 70 | ZWE | Zimbabwe | 2010 | 0 | 378.200000 | 1 | 1 | 0.0 | 3.217000 | 1 | 0 | 0 | no_crisis |
1056 | 70 | ZWE | Zimbabwe | 2011 | 0 | 361.900000 | 1 | 1 | 0.0 | 4.920000 | 1 | 0 | 0 | no_crisis |
1057 | 70 | ZWE | Zimbabwe | 2012 | 0 | 361.900000 | 1 | 1 | 0.0 | 3.720000 | 1 | 0 | 0 | no_crisis |
1058 | 70 | ZWE | Zimbabwe | 2013 | 0 | 361.900000 | 1 | 1 | 0.0 | 1.632000 | 1 | 0 | 0 | no_crisis |
1059 rows × 14 columns
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1059 entries, 0 to 1058 Data columns (total 14 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 case 1059 non-null int64 1 cc3 1059 non-null object 2 country 1059 non-null object 3 year 1059 non-null int64 4 systemic_crisis 1059 non-null int64 5 exch_usd 1059 non-null float64 6 domestic_debt_in_default 1059 non-null int64 7 sovereign_external_debt_default 1059 non-null int64 8 gdp_weighted_default 1059 non-null float64 9 inflation_annual_cpi 1059 non-null float64 10 independence 1059 non-null int64 11 currency_crises 1059 non-null int64 12 inflation_crises 1059 non-null int64 13 banking_crisis 1059 non-null object dtypes: float64(3), int64(8), object(3) memory usage: 116.0+ KB
df.tail(10)
case | cc3 | country | year | systemic_crisis | exch_usd | domestic_debt_in_default | sovereign_external_debt_default | gdp_weighted_default | inflation_annual_cpi | independence | currency_crises | inflation_crises | banking_crisis | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
1049 | 70 | ZWE | Zimbabwe | 2004 | 1 | 5.600000e-23 | 1 | 1 | 0.0 | 1.327468e+02 | 1 | 1 | 1 | crisis |
1050 | 70 | ZWE | Zimbabwe | 2005 | 1 | 8.460000e-22 | 1 | 1 | 0.0 | 5.858444e+02 | 1 | 1 | 1 | crisis |
1051 | 70 | ZWE | Zimbabwe | 2006 | 1 | 3.000000e-19 | 1 | 1 | 0.0 | 1.281114e+03 | 1 | 1 | 1 | crisis |
1052 | 70 | ZWE | Zimbabwe | 2007 | 1 | 1.900000e-16 | 1 | 1 | 0.0 | 6.627989e+04 | 1 | 1 | 1 | crisis |
1053 | 70 | ZWE | Zimbabwe | 2008 | 1 | 2.000000e-03 | 1 | 1 | 0.0 | 2.198970e+07 | 1 | 1 | 1 | crisis |
1054 | 70 | ZWE | Zimbabwe | 2009 | 1 | 3.548000e+02 | 1 | 1 | 0.0 | -7.670000e+00 | 1 | 1 | 0 | crisis |
1055 | 70 | ZWE | Zimbabwe | 2010 | 0 | 3.782000e+02 | 1 | 1 | 0.0 | 3.217000e+00 | 1 | 0 | 0 | no_crisis |
1056 | 70 | ZWE | Zimbabwe | 2011 | 0 | 3.619000e+02 | 1 | 1 | 0.0 | 4.920000e+00 | 1 | 0 | 0 | no_crisis |
1057 | 70 | ZWE | Zimbabwe | 2012 | 0 | 3.619000e+02 | 1 | 1 | 0.0 | 3.720000e+00 | 1 | 0 | 0 | no_crisis |
1058 | 70 | ZWE | Zimbabwe | 2013 | 0 | 3.619000e+02 | 1 | 1 | 0.0 | 1.632000e+00 | 1 | 0 | 0 | no_crisis |
df.describe()
case | year | systemic_crisis | exch_usd | domestic_debt_in_default | sovereign_external_debt_default | gdp_weighted_default | inflation_annual_cpi | independence | currency_crises | inflation_crises | |
---|---|---|---|---|---|---|---|---|---|---|---|
count | 1059.000000 | 1059.000000 | 1059.000000 | 1059.000000 | 1059.000000 | 1059.000000 | 1059.000000 | 1.059000e+03 | 1059.000000 | 1059.000000 | 1059.000000 |
mean | 35.613787 | 1967.767705 | 0.077432 | 43.140831 | 0.039660 | 0.152975 | 0.006402 | 2.084889e+04 | 0.776204 | 0.132200 | 0.129367 |
std | 23.692402 | 33.530632 | 0.267401 | 111.475380 | 0.195251 | 0.360133 | 0.043572 | 6.757274e+05 | 0.416984 | 0.349847 | 0.335765 |
min | 1.000000 | 1860.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | -2.850214e+01 | 0.000000 | 0.000000 | 0.000000 |
25% | 15.000000 | 1951.000000 | 0.000000 | 0.195350 | 0.000000 | 0.000000 | 0.000000 | 2.086162e+00 | 1.000000 | 0.000000 | 0.000000 |
50% | 38.000000 | 1973.000000 | 0.000000 | 0.868400 | 0.000000 | 0.000000 | 0.000000 | 5.762330e+00 | 1.000000 | 0.000000 | 0.000000 |
75% | 56.000000 | 1994.000000 | 0.000000 | 8.462750 | 0.000000 | 0.000000 | 0.000000 | 1.164405e+01 | 1.000000 | 0.000000 | 0.000000 |
max | 70.000000 | 2014.000000 | 1.000000 | 744.306139 | 1.000000 | 1.000000 | 0.400000 | 2.198970e+07 | 1.000000 | 2.000000 | 1.000000 |
We need to get rid of value 2 in currency_crises as there shoul be only 0 and 1.
df['currency_crises'] = df['currency_crises'].replace(2,np.nan)
df = df.dropna()
years = df.year.unique()
len(years)
155
There are 155 years in the dataset
countries = df["country"].unique()
countries
array(['Algeria', 'Angola', 'Central African Republic', 'Ivory Coast', 'Egypt', 'Kenya', 'Mauritius', 'Morocco', 'Nigeria', 'South Africa', 'Tunisia', 'Zambia', 'Zimbabwe'], dtype=object)
len(countries)
13
And 13 African countries
df["banking_crises"] = np.where(df['banking_crisis'] == "crisis", 1, 0)
<ipython-input-12-674990f9e389>: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 df["banking_crises"] = np.where(df['banking_crisis'] == "crisis", 1, 0)
We need a proper column with 0/1 values instead of str.
Okay, let's start. The idea is to identify what are the interconnections in the dataset, what factors lead to crises in Africa and what does not. It's also good to know whether being independent affected financial stability of the African countries.
dependent = df[df.independence == 0]
independent = df[df.independence == 1]
Systemic crisis means the nationwide banking crisis which its impact spreads to the whole banking sector. There are two conditions to be met: 1) significant signs of financial distress are in a majority part of the banking system 2) significant banking policy intervention measures are implemented by the appropriate financial authorities in response to significant losses amongst the individual components of the banking system In this work we're going to consider systemic crisis applied to the economy of particular country. Obviously, the more often such crises happen, the worse economic situation in country is.
sys_crises_per_country_dependent = dependent.groupby("country",as_index=False)["systemic_crisis"].sum()
sys_crises_per_country_independent = independent.groupby("country",as_index=False)["systemic_crisis"].sum()
countrues_sorted_dep = sys_crises_per_country_dependent.sort_values(by = ["systemic_crisis"], ascending=False)
countrues_sorted_indep = sys_crises_per_country_independent.sort_values(by = ["systemic_crisis"], ascending=False)
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_dep["country"], countrues_sorted_dep["systemic_crisis"],color=(0.7, 0.7, 0.7, 0.6))
plt.title("Systemic crises for countries while being dependent")
plt.show()
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_indep["country"], countrues_sorted_indep["systemic_crisis"],color=(0.3, 0.4, 0.6, 0.6))
plt.title("Systemic crises for countries while being independent")
plt.show()
Data shows that systemic crisis started after counties became independent.
Central African Republic has the highest value for systemic crisis count. Angola, Mauritius and South Africa gave not experienced this crisis inn the given period. And what about other crises?
A banking crisis is a financial crisis that affects banking activity. Banking crises include bank runs, which affect single banks; banking panics, which affect many banks; and systemic banking crises, in which a country experiences many defaults and financial institutions and corporations face great difficulties repaying contracts.A banking crisis is marked by bank runs that lead to the demise of financial institutions, or by the demise of a financial institution that starts a string of similar demises.
bank_crises_per_country_dependent = dependent.groupby("country",as_index=False)["banking_crises"].sum()
bank_crises_per_country_independent = independent.groupby("country",as_index=False)["banking_crises"].sum()
countrues_sorted_dep_bank = bank_crises_per_country_dependent.sort_values(by = ["banking_crises"], ascending=False)
countrues_sorted_indep_bank = bank_crises_per_country_independent.sort_values(by = ["banking_crises"], ascending=False)
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_dep_bank["country"], countrues_sorted_dep_bank["banking_crises"],color=(0.2, 0.2, 0.2, 0.6))
plt.title("Banking crises for countries while being dependent")
plt.show()
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_indep_bank["country"], countrues_sorted_indep_bank["banking_crises"],color=(0.9, 0.9, 0.6, 0.6))
plt.title("Banking crises for countries while being independent")
plt.show()
All countries between after became independent were affected by banking crisis. Central African Republic, Zimbabwe and Egypt suffered the most.
It looks that there certainly is an interconnection between banking and systemic crisis. Let's take a look!
Here we examine if systematic crisis always means banking crisis too. Let's take al date regardless of being dependent or not.
data_with_sys_crisis = df[df.systemic_crisis == 1]
data_with_sys_crisis.country.unique()
array(['Algeria', 'Central African Republic', 'Ivory Coast', 'Egypt', 'Kenya', 'Morocco', 'Nigeria', 'Tunisia', 'Zambia', 'Zimbabwe'], dtype=object)
First of all, collect all data where systemic crisis did happen...
plt.figure(figsize=(10,6))
bank_sum_for_sys = data_with_sys_crisis.groupby("country",as_index=False)["banking_crises"].sum()
bank_and_sys_countries_sorted = bank_sum_for_sys.sort_values(by = ["banking_crises"], ascending=False)
plt.figure(figsize=(20,6))
plt.bar(bank_and_sys_countries_sorted["country"], bank_and_sys_countries_sorted["banking_crises"],color=(0.2, 0.5, 0.9, 0.6))
<BarContainer object of 10 artists>
<Figure size 720x432 with 0 Axes>
And after that make a barchart with those countries who faced systemic crisis and show how often did they have banking crisis.
The fact form the dataset is that if systemic crisis happened, banking crisis will also affect the country
Do they happen at the same time?
fig = plt.figure(figsize=(15,10))
fig.subplots_adjust(hspace=0.7, wspace=0.4)
for i in range(0, len(countries)):
ax = fig.add_subplot(4, 4, i + 1)
sns.barplot(x="year", y="systemic_crisis", data=df[df.country == countries[i]])
plt.title(countries[i])
fig = plt.figure(figsize=(15,10))
fig.subplots_adjust(hspace=0.7, wspace=0.4)
for i in range(0, len(countries)):
ax = fig.add_subplot(4, 4, i + 1)
sns.barplot(x="year", y="banking_crises", data=df[df.country == countries[i]])
plt.title(countries[i])
Yep! Banking crisis definitely follow the time systemic risk happens.
Finally, let's see heatmap od correlations:
years = df.year.unique() plt.figure(figsize=(10,10)) plt.title('Heatmap') sns.heatmap(df.corr(), annot=True, cmap=sns.diverging_palette(20, 220, n=200))
It's clearly seen than banking crises is highly positively correlated with systemic crises.
Inflation crisis means very high and typically accelerating inflation. It quickly erodes the real value of the local currency, as the prices of all goods increase. This causes people to minimize their holdings in that currency as they usually switch to more stable foreign currencies. There is no need to explain why this crisis is dangerous and dectructive for the economy.
inf_crises_per_country_dependent = dependent.groupby("country",as_index=False)["inflation_crises"].sum()
inf_crises_per_country_independent = independent.groupby("country",as_index=False)["inflation_crises"].sum()
countrues_sorted_dep_inf = inf_crises_per_country_dependent.sort_values(by = ["inflation_crises"], ascending=False)
countrues_sorted_indep_inf = inf_crises_per_country_independent.sort_values(by = ["inflation_crises"], ascending=False)
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_dep_inf["country"], countrues_sorted_dep_inf["inflation_crises"],color=(0.7, 0.7, 0.7, 0.6))
plt.title("Inflation crises for countries while being dependent")
plt.show()
plt.figure(figsize=(15,7))
plt.bar(countrues_sorted_indep_inf["country"], countrues_sorted_indep_inf["inflation_crises"],color=(0.3, 0.4, 0.6, 0.6))
plt.title("Inflation crises for countries while being independent")
plt.show()
fig = plt.figure(figsize=(15,15))
fig.subplots_adjust(hspace=0.7, wspace=0.4)
plt.style.use('seaborn-paper')
for i in range(0, len(countries)):
ax = fig.add_subplot(4, 4, i + 1)
df_country = df[df.country == countries[i]]
sns.lineplot(df_country.year, df.inflation_annual_cpi, ci = None)
plt.title(countries[i])
C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn( C:\Users\ASUS\anaconda3\lib\site-packages\seaborn\_decorators.py:36: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation. warnings.warn(
Here we cann idenntify when inflatio rate was the highest for each coutry. But what about independence?
sns.set_style("ticks", {"xtick.major.size": 10, "ytick.major.size": 10})
plt.style.use('seaborn-paper')
fig, axes = plt.subplots(ncols=4, nrows=4, figsize=(15,15))
axes = axes.flatten()
for i, ax in zip(countries, axes):
sns.lineplot(x = 'year', y = 'inflation_annual_cpi', hue = 'independence',
data = df[df['country'] == i], ax = ax)
ax.set_xlabel('Year')
ax.set_ylabel('Inflation rate')
ax.set_title('{}'.format(i))
ax.get_legend().remove()
handles, labels = ax.get_legend_handles_labels()
fig.legend(handles, labels, loc=1)
fig.subplots_adjust(top=0.95)
for i in range(13,16):
fig.delaxes(axes[i])
plt.tight_layout()