"""
# Tutorial: Bar Charts in Python

This tutorial demonstrates the use of bar charts in Python. We will use both Matplotlib and Seaborn and the **FIFA 19 player dataset**. It can also be used as a quick reference when you are plotting bar charts in Python.
"""
"""
## Loading Data and Cleaning
"""
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

data = pd.read_csv("../input/data.csv")
# These columns are links and will not be used in this notebook
data = data.drop(axis = 1, columns=['Photo','Flag', 'Club Logo'])  
data.head()
"""
The 'Value' and 'Wage' columns have a Euro (€) sign. We need to remove the Euro sign and transform into numbers.
"""
# Clean up value and wage columns
def get_value(value):
    value_num = value.replace('€','')
    if 'M' in value_num:
        value_num = float(value_num.replace('M','')) * 1000000
    elif 'K' in value_num:
        value_num = float(value_num.replace('K','')) * 1000
    return float(value_num) # Ensure both columns are in float format

data['Value'] = data['Value'].apply(lambda x: get_value(x))
data['Wage'] = data['Wage'].apply(lambda x: get_value(x))

data.head()
"""
## Basic Bar Plots

We start with the basic bar plots of the count of players by Nationality in this dataset. To plot bar charts in Python we have four ways: **(1) .plot() method in pandas; (2) plt.bar() in matplotlib; (3) barplot() in Seaborn; (4) countplot() in Seaborn.**
"""
# Create the top_10_nation pandas series
by_nation = data.Nationality.value_counts()
top_10_nation = by_nation[:10]
top_10_nation
# Method 1: .plot() in pandas
top_10_nation.plot(kind='bar'); # The ';' is to avoid showing a message before the chart
# We can also plot horizontally by using 'barh' in 'kind' argument
top_10_nation.plot(kind='barh');
"""
I prefer using horizontal bars in most cases because the axis labels can be seen more easily.
"""
# Method 2: plt.bar() in matplotlib - we input x and y arguments
plt.bar(top_10_nation.index, top_10_nation);
# Horizontally
plt.barh(top_10_nation.index, top_10_nation);
"""
The bars are thicker than the first method, and by default it is shown in single color. But the vertical bars, the axis labels do not rotate and it looks messy.
"""
# Method 3: barplot() in Seaborn
sns.barplot(top_10_nation.index, top_10_nation);
# To plot horizontal bars, just flip the first two arguments and seaborn will sort out the orientation itself
sns.barplot(top_10_nation, top_10_nation.index);
"""
Default in Seaborn is to put the first value at the top. To do the same for .plot(), we need to reverse the sorting order of the input data:
"""
top_10_nation_r = top_10_nation.sort_values(ascending=True)
top_10_nation_r.plot(kind='barh');
"""
We can also plot bar chart of counts directly from data using countplot() function in Seaborn:
"""
# Method 4: Countplot
sns.countplot(y = 'Nationality', data=data);
"""
All countries will be plotted and the labels will be messed up. To plot only the top 10, we need to specify in 'order' argument:
"""
sns.countplot(y = 'Nationality', data=data, order = data.Nationality.value_counts().iloc[:10].index);
"""
For more details of the functions above, please check the documentation:
- [pandas.Series.plot()](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.plot.html)
- [matplotlib.pyplot.barh()](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.barh.html)
- [seaborn.barplot()](https://seaborn.pydata.org/generated/seaborn.barplot.html)
- [seaborn.countplot()](https://seaborn.pydata.org/generated/seaborn.countplot.html)
"""
"""
## Simple Customization

This part will demonstrate how to customize colors, figure and font size, axis labels, and show values in charts. We will plot the most valuable English players in this example.
"""
england = data.loc[data.Nationality == 'England'].sort_values('Value', ascending = False)
england.head()
# Top 30 players by value
england_30 = england.head(30).loc[:, ['Name','Value']]
sns.barplot(england_30.Value, england_30.Name);
"""
We want to make the following changes:
1. Add a title to the plot;
2. Enlarge the plot so that the player names can be seen more clearly;
3. Instead of scientific notation (1e7), we show the value in millions (and change the x-axis label to Value (M EUR))
"""
plt.figure(figsize=(10,7)) # Specify figure size
sns.barplot(england_30.Value / 1000000 , england_30.Name) # in millions
plt.title('Top 30 English Players by Value', fontsize=16)
plt.xlabel('Value (EUR M)')
plt.yticks(fontsize=12) # Larger tick labels
plt.xticks(fontsize=12)
plt.show()
"""
The default colors in seaborn is beautiful, but if we want to specify a single color or another set of colors, we can specify in the plot function:
"""
plt.figure(figsize=(10,7)) # Specify figure size
sns.barplot(england_30.Value / 1000000 , england_30.Name, color = 'red') # color argument specifies a single color
plt.title('Top 30 English Players by Value', fontsize=16)
plt.xlabel('Value (EUR M)')
plt.yticks(fontsize=12) # Larger tick labels
plt.xticks(fontsize=12)
plt.show()
plt.figure(figsize=(10,7)) # Specify figure size
sns.barplot(england_30.Value / 1000000 , england_30.Name, palette = 'spring') # palette argument specifies the color map
plt.title('Top 30 English Players by Value', fontsize=16)
plt.xlabel('Value (EUR M)')
plt.yticks(fontsize=12) # Larger tick labels
plt.xticks(fontsize=12)
plt.show()
"""
For the list of color and palette names, please see below links:
- [Colors can be used in color argument](https://matplotlib.org/gallery/color/named_colors.html)
- [Colormaps can be used in palette argument](https://matplotlib.org/2.0.2/examples/color/colormaps_reference.html)
"""
"""
## Data Label, Annotation, and Reference Line

We can show the data values on the chart, and add reference lines for comparison. We plot the wage of Arsenal Players:
"""
data['Club'].fillna('None', inplace=True) # Clean up some null values to avoid errors in the next step
arsenal = data[data['Club'].str.contains('Arsenal')]
arsenal = arsenal.sort_values('Wage', ascending=False)
arsenal.head()
"""
Here, we want to plot:
- The wage of Arsenal players in descending order
- Add actual values of their wages alongside each bar
- Add a vertical line showing average wage for comparison, and show the average value on the chart
"""
avg_arsenal = np.mean(arsenal['Wage'])

plt.figure(figsize=(10,8))
g = sns.barplot(arsenal.Wage / 1000 , arsenal.Name) # in thousands
# Adding labels of data value
for i, v in enumerate(arsenal.Wage / 1000):
    g.text(v+1, i, str(int(v))) # The three arguments are x-coordinate, y-coordinate, and the label
plt.title('Wage of Arsenal Players')
plt.xlabel('Wage (EUR K)')
plt.axvline(avg_arsenal/1000) # The vertical line
g.text(avg_arsenal/1000 + 5, 20, 'Mean wage: ' + str(int(avg_arsenal/1000)) + 'K') # Annotation of the line
plt.show()
"""
That's it for now. Happy charting!
"""