numpy - pandas

Dans cette section:

Licence CC BY-NC-ND, Thierry Parmentelat & Arnaud Legout

from IPython.display import HTML
HTML(filename="_static/style.html")

numpy - pandas#

ce sont deux librairies qui ne font pas partie de la librairie standard, mais qui ont une importance considérable dans l’écosystème Python
il est important de les connaitre a minima - ne serait-ce que pour ne pas réinventer la roue !

numpy#

les structures de données natives de Python - listes, tuples, dictionnaires, ensembles, etc… - sont très pratiques, mais pas super efficaces !
si vous avez un besoin de faire des calculs intensifs, cela va vite être problématique - escomptez un rapport de performance de l’ordre de 70 à 100 fois plus lent ! que du code compilé…
numpy apporte une solution très raisonnable

  • les moins:

    • on manipule des données homogènes et contigües

    • ce qui signifie donc aussi taille fixe, et pas de mélange de types genre None ou autres

  • les plus:

    • très efficace (comparable à du code compilé) - tire profit de SIMD

    • choix des types concrets (comme avec du code compilé, pensez uint8), donc économe en mémoire

    • en dimension quelconque

programmation vectorielle#

avec numpy on change de paradigme:
jusqu’ici on vous a dit “en Python, on itère de préférence avec la boucle for
eh bien avec numpy on vous dit: “surtout n’écrivez pas de boucle for” !!

pourquoi ? eh bien pour tirer profit au maximum de l’architecture des ordinateurs modernes, en numpy on va utiliser massivement la programmation vectorielle, ce qui signifie qu’à chaque fois que possible on va s’exprimer à base d’opérations sur tout le tableau, ce qui implicitement signifie sur tous les éléments d’un tableau

c’est un sujet qui mérite une formation à part entière, mais juste pour donner un aperçu voici comment on dessinerait la courbe d’un sinus

import numpy as np

# un tableau de 200 nombres bien répartis entre 0 et 4π
X = np.linspace(0, 4*np.pi, 200)

# pour calculer les 200 sinus, on ne fait **surtout pas de for**
# mais tout simplement
Y = np.sin(X)
# ce qu'on peut dessiner comme ceci
import matplotlib.pyplot as plt

plt.plot(X, Y);
_images/e044c7b2ac09b241df2d2c1389eddee52f530821d14acdda6750781d57b2f1f5.png

pandas#

c’est l’arme absolue pour charger des données de type tabulaire - comme dans une table de base de données
c’est-à-dire des données en 2 dimensions où les colonnes sont homogènes
à nouveau c’est un sujet à soi tout seul, mais ici encore il faut absolument savoir que ça existe!!

avec pandas, on peut faire en gros tout ce qui possible en SQL - la seule restriction étant que pandas travaille en mémoire
mais fonctionnellement, on trouve dans pandas les équivalents de tous les traits de SQL: select, join, where, sort, …
avec en plus des facillités pour traiter les séries temporelles, mais là on s’égare

import pandas as pd

df = pd.read_csv("../data/Worldwide-Earthquake-database.csv")

df.head()
I_D FLAG_TSUNAMI YEAR MONTH DAY HOUR MINUTE SECOND FOCAL_DEPTH EQ_PRIMARY ... TOTAL_MISSING TOTAL_MISSING_DESCRIPTION TOTAL_INJURIES TOTAL_INJURIES_DESCRIPTION TOTAL_DAMAGE_MILLIONS_DOLLARS TOTAL_DAMAGE_DESCRIPTION TOTAL_HOUSES_DESTROYED TOTAL_HOUSES_DESTROYED_DESCRIPTION TOTAL_HOUSES_DAMAGED TOTAL_HOUSES_DAMAGED_DESCRIPTION
0 1 No -2150 NaN NaN NaN NaN NaN 7.3 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 2 Yes -2000 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 3 No -2000 NaN NaN NaN NaN NaN 18.0 7.1 ... NaN NaN NaN NaN NaN 1.0 NaN 1.0 NaN NaN
3 5877 Yes -1610 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 3.0 NaN NaN NaN NaN
4 8 No -1566 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 47 columns

# les colonnes
df.columns
Index(['I_D', 'FLAG_TSUNAMI', 'YEAR', 'MONTH', 'DAY', 'HOUR', 'MINUTE',
       'SECOND', 'FOCAL_DEPTH', 'EQ_PRIMARY', 'EQ_MAG_MW', 'EQ_MAG_MS',
       'EQ_MAG_MB', 'EQ_MAG_ML', 'EQ_MAG_MFA', 'EQ_MAG_UNK', 'INTENSITY',
       'COUNTRY', 'STATE', 'LOCATION_NAME', 'LATITUDE', 'LONGITUDE',
       'REGION_CODE', 'DEATHS', 'DEATHS_DESCRIPTION', 'MISSING',
       'MISSING_DESCRIPTION', 'INJURIES', 'INJURIES_DESCRIPTION',
       'DAMAGE_MILLIONS_DOLLARS', 'DAMAGE_DESCRIPTION', 'HOUSES_DESTROYED',
       'HOUSES_DESTROYED_DESCRIPTION', 'HOUSES_DAMAGED',
       'HOUSES_DAMAGED_DESCRIPTION', 'TOTAL_DEATHS',
       'TOTAL_DEATHS_DESCRIPTION', 'TOTAL_MISSING',
       'TOTAL_MISSING_DESCRIPTION', 'TOTAL_INJURIES',
       'TOTAL_INJURIES_DESCRIPTION', 'TOTAL_DAMAGE_MILLIONS_DOLLARS',
       'TOTAL_DAMAGE_DESCRIPTION', 'TOTAL_HOUSES_DESTROYED',
       'TOTAL_HOUSES_DESTROYED_DESCRIPTION', 'TOTAL_HOUSES_DAMAGED',
       'TOTAL_HOUSES_DAMAGED_DESCRIPTION'],
      dtype='object')
# select year, latitude, longitude, intensity from df where eq_primary >= 7
extract = df.loc[df.EQ_PRIMARY >= 7].loc[:, ['YEAR', 'LATITUDE', 'LONGITUDE', 'INTENSITY']]

extract.head()
YEAR LATITUDE LONGITUDE INTENSITY
0 -2150 31.1 35.5 NaN
2 -2000 38 58.2 10.0
14 -479 39.7 23.3 9.0
16 -426 38.9 22.7 10.0
17 -400 35.5 51.8 NaN