import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
%matplotlib inline

"""
Explanation: Visualisation de données avec pandas et matplotlib
Germain Salvato Vallverdu germain.vallverdu@univ-pau.fr
Ce notebook présente l'utilisation de pandas et 
de matplotlib pour la lecture de données en python 
et la constructions de quelques représentations graphiques avec matplotlib.
Les données utilisées dans cet exemple sont issues de la base de données ouverte de 
la Communauté d'Agglomération de Pau-Pyrénées (CAPP) opendata.agglo-pau.fr.
End of explanation
"""


df = pd.read_csv("Evolution_et_structure_de_la_population/Evolution_structure_population.csv", sep=";")
df = df.set_index("libgeo")
df

"""
Explanation: Chargement des données à partir d'un fichier CSV
Les données proviennent de http://opendata.agglo-pau.fr/index.php/fiche?idQ=27
Lors du téléchargement de l'archive, le fichier csv contient les données et un fichiers excel décrit le contenu de chaque colonne.
Ici, le fichier csv est lu directement avec la fonction read_csv de pandas, en précisant que le séparateur est un point virgule. Cette fonction retourne un objet DataFrame qui s'apparente à un tableau de données. On précise également que LIBGEO, le nom de la commune, sera utilisé comme index de la DataFrame de pandas. Chaque ligne portera alors le nom de la ville correspondante.
End of explanation
"""


pop11 = df["p11_pop"]
pop11 = pop11.sort_values(ascending=True)
pop11

"""
Explanation: Un diagramme en barres
Premièrement nous allons construire un graphique sous forme de barres horizontales, représentant la population dans chaque ville de l'aglomération de Pau-Pyrénées en 2011.
Nous utiliserons un diagramme en barre horizontale avec la fonction barh de matplotlib (exemple).
Commençons par extraire la colonne qui nous intéresse (P11_POP) et classons les valeurs par ordre croissant.
End of explanation
"""


# figure
fig = plt.figure(figsize=(10, 10))
ax = fig.add_subplot(111)
ax.set_title("Population de la CAPP en 2011", fontsize=20)
# bar plot
ax.barh(
    # position et longueur des barres
    bottom=range(pop11.count()), 
    width=pop11,
    # labels
    align="center", 
    tick_label=pop11.index,
    # couleurs et traits
    color="RoyalBlue",
    linewidth=0
)
# format axis
ax.set_frame_on(False)
ax.set_xticks([])
ax.tick_params("both", length=0)
ax.vlines(0, -1, pop11.count(), color="gray", linewidth=4)
# add the value at the end of the bar
for y, pop in enumerate(pop11):
    ax.annotate(
        # texte
        "%.0f" % pop,
        # position
        xy=(pop, y), 
        xytext=(5, -4), 
        textcoords="offset points", 
        # format
        fontsize=14, 
        color="RoyalBlue"
    )
fig.savefig("barh_pop.png", dpi=300)

"""
Explanation: Construisons maintenant le graphique avec les données ci-dessus.
End of explanation
"""


import squarify

"""
Explanation: Réalisation d'une Treemap
Pour faire ce graphique on va utiliser la librairie squarify. La superficie des rectangles représentera la superficie de la commune. Une échelle de couleur donnera la population de la commune.
End of explanation
"""


df2 = df[["superf", "p11_pop"]]
df2 = df2.sort_values(by="superf", ascending=False)
df2

"""
Explanation: Extraction de la superficie des communes et de la population en 2011. Le tableau est trié par ordre décroissant de la superficie.
End of explanation
"""


print("Pau: superficie = %d km2, population = %d\n" % (df2["superf"]["PAU"], df2["p11_pop"]["PAU"]))

"""
Explanation: Superficie et population de Pau :
End of explanation
"""


x = 0.
y = 0.
width = 100.
height = 100.
cmap = matplotlib.cm.viridis

# color scale on the population
# min and max values without Pau
mini, maxi = df2.drop("PAU").p11_pop.min(), df2.drop("PAU").p11_pop.max()
norm = matplotlib.colors.Normalize(vmin=mini, vmax=maxi)
colors = [cmap(norm(value)) for value in df2.p11_pop]
colors[1] = "#FBFCFE"

# labels for squares
labels = ["%s\n%d km2\n%d hab" % (label) for label in zip(df2.index, df2.superf, df2.p11_pop)]
labels[11] = "MAZERES-\nLEZONS\n%d km2\n%d hab" % (df2["superf"]["MAZERES-LEZONS"], df2["p11_pop"]["MAZERES-LEZONS"])

# make plot
fig = plt.figure(figsize=(12, 10))
fig.suptitle("Population et superficie des communes de la CAPP", fontsize=20)
ax = fig.add_subplot(111, aspect="equal")
ax = squarify.plot(df2.superf, color=colors, label=labels, ax=ax, alpha=.7)
ax.set_xticks([])
ax.set_yticks([])
ax.set_title("L'aire de chaque carré est proportionnelle à la superficie de la commune\n", fontsize=14)

# color bar
# create dummy invisible image with a color map
img = plt.imshow([df2.p11_pop], cmap=cmap)
img.set_visible(False)
fig.colorbar(img, orientation="vertical", shrink=.96)

fig.text(.76, .9, "Population", fontsize=14)
fig.text(.5, 0.1,
         "Superficie totale %d km2, Population de la CAPP : %d hab" % (df2.superf.sum(), df2.p11_pop.sum()),
         fontsize=14,
         ha="center")
fig.text(.5, 0.07,
         "Source : http://opendata.agglo-pau.fr/",
         fontsize=14,
         ha="center")

fig.savefig("treemap_capp_pau.png", dpi=300)

"""
Explanation: Représentation en Treemaps avec les fonctions inclues dans squarify.
End of explanation
"""


# noms des colonnes:
years = [99] + list(range(0, 12))
naissance = ["nais%02d" % y for y in years]
deces = ["dece%02d" % y for y in years]

# nouvelle DataFrame avec les deces et les naissances à Pau en fonction des années
df4 = pd.DataFrame(
    data={
        "naissance": df.loc["PAU", naissance].values, 
        "deces": df.loc["PAU", deces].values
    },
    index=[1999 + i for i in range(0, 13)]
)
df4

"""
Explanation: Graphique xy classique
Dans ce graphique nous allons simplement représenter le nombre de naissances et de décés à Pau entre 1999 et 2011. C'est un graphique très simple à réaliser avec pandas. Nous allons voir tout d'abord comment extraire les données puis nous ferons un premier graphique basique avec la fonction plot() de pandas. Ensuite, nous ajouterons une courbe de tendance linéaire avec lineregress() de scipy.
Tout d'abord nous devons extraire les colonnes NAISXX et DECEXX du tableau global pour la ligne concernant Pau.
End of explanation
"""


df4.plot(
    marker="o", 
    linestyle="dashed", 
    title="Naissances et décés à Pau entre 1999 et 2011",
    figsize=(8, 6),
    fontsize=16,
    xlim=(1998, 2012)
)

"""
Explanation: À partir de ce type de tableau, il est très simple de tracer des courbes avec la fonction plot() de pandas. Les arguments sont du même type que ceux de matplotlib :
End of explanation
"""


from scipy.stats import linregress
# pour les naissances
p_naissance, i_naissance, *others = linregress(x=df4.index, y=df4.naissance)
df4["trend_naissance"] = p_naissance * df4.index + i_naissance
# pour les décés
p_deces, i_deces, *others  = linregress(x=df4.index, y=df4.deces)
df4["trend_deces"] = p_deces * df4.index + i_deces

df4

colors = sns.color_palette("husl", 2)
# figure
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111)
ax.set_title("Naissances et décés à Pau entre 1999 et 2011", color="#555555")
# plot the differents quantities
ax.plot(df4.index, df4.naissance, marker="o", label="Naissances", linestyle="--", linewidth=.5, color=colors[0])
ax.plot(df4.index, df4.deces, marker="o", label="Décés", linestyle="--", linewidth=.5, color=colors[1])
ax.plot(df4.index, df4.trend_naissance, label="", color=colors[0])
ax.plot(df4.index, df4.trend_deces, label="", color=colors[1])
# format and style
ax.set_xlabel("Année")
ax.set_ylabel("Nombre de naissances ou décés")
ax.legend()
fig.savefig("xy_pop.png", dpi=300)

"""
Explanation: Ajoutons maintenant une courbe de tendance et ajoutons les données au tableau (bien que deux points seulement auraient suffit) :
End of explanation
"""


columns = {
    "c10_pop15p_cs1": "agriculteurs",
    "c10_pop15p_cs2": "Artisans",
    "c10_pop15p_cs3": "Cadres",
    "c10_pop15p_cs4": "Intermédiaires",
    "c10_pop15p_cs5": "Employés",
    "c10_pop15p_cs6": "Ouvriers",
    "c10_pop15p_cs7": "Retraités",
    "c10_pop15p_cs8": "Autres"
}
df_cat = df[list(columns.keys())]
df_cat = df_cat.rename(columns=columns)
# add the sum over CAPP
df_cat.loc["CAPP"] = df_cat.sum(axis=0)
df_cat["total"] = df_cat.sum(axis=1)
df_cat

"""
Explanation: Camembert ou pie chart ou wedge chart
Le fichiers de données de la CAPP contient aussi les catégorie socio-professionnelle pour chaque commune. Nous allons les représenter avec un diagramme de type camembert.
Commençons par regrouper les données dans une nouvelle table et faisons la somme sur toutes les communes.
End of explanation
"""


fig = plt.figure(figsize=(18, 10))
fig.suptitle("Catégories socio-professionnelles de la CAPP en 2010\nPau et Billère", fontsize=20, color="#444444")
width = .3

# color scale
colors = ["#F4A460", '#E24A33', '#348ABD', '#988ED5', '#777777', '#FBC15E', '#8EBA42', '#FFB5B8']

# PAU et CAPP
ax1 = fig.add_subplot(121, aspect="equal")
pau_pie = ax1.pie(
    # data
    df_cat.loc["PAU"].drop("total"), 
    # wedges
    colors=colors, 
    radius=1, 
    wedgeprops={"width": width, "linewidth": 1},
    # labels
    autopct="%4.1f%%",
    pctdistance=.85
)
capp_pie = ax1.pie(
    df_cat.loc["CAPP"].drop("total"), 
    colors=colors, 
    radius=1 - width,
    wedgeprops={"width": width, "linewidth": 1},
    autopct="%4.1f%%",
    pctdistance=.75
)
ax1.set_title("Pau", fontsize=18, color="#555555")
ax1.text(.1, -.1, "CAPP", fontsize=18, color='#555555')
ax1.text(.8, -.7, "Pau", size=18, color='#555555')

# Billere et CAPP
ax2 = fig.add_subplot(122, aspect="equal")
bill_pie = ax2.pie(
    df_cat.loc["BILLERE"].drop("total"), 
    colors=colors, 
    radius=1, 
    wedgeprops={"width": width, "linewidth": 1},
    autopct="%4.1f%%",
    pctdistance=.85
)
capp_pie = ax2.pie(
    df_cat.loc["CAPP"].drop("total"), 
    colors=colors, 
    radius=1 - width,
    wedgeprops={"width": width, "linewidth": 1},
    autopct="%4.1f%%",
    pctdistance=.75
)
ax2.set_title("Billère", fontsize=18, color="#555555")
ax2.text(.1, -.1, "CAPP", size=18, color='#555555')
ax2.text(.8, -.7, "Billère", size=18, color='#555555')

# legende
fig.legend(pau_pie[0], df_cat.columns.values, fontsize=16)
fig.subplots_adjust(wspace=0)
fig.savefig("capp_pie.png", dpi=300)

"""
Explanation: Construction du graphique :
End of explanation
"""


