Une rapide introduction
CentraleSupélec
La librairie pandas est développée pour l’analyse de données.
Site du projet https://pandas.pydata.org/
Cheat sheet, Data Wrangling with pandas
Les très bons Getting started tutorials
Autres ressources : Workshop pandas de Stéfanie Molin et son livre Hands-On Data Analysis with Pandas: A Python data science handbook for data collection, wrangling, analysis, and visualization
Installation
Avec uv :
Avec pip :
Beaucoup d’exemples par la suite viennent du guide utilisateur Pandas.
une série peut être indexée, slicée, etc.. comme un tableau numpy avec iloc, et comme un dictionnaire avec [..] ou loc()
une DataFrame est une collection de séries de données (comme une base de données)
d = {
"one": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
"two": pd.Series([1.0, 2.0, 3.0, 4.0], index=["a", "b", "c", "d"]),
"three": pd.Series([1.0, 2.0 ], index=["b", "d"])
}
df = pd.DataFrame(d)
print(df)
one two three
a 1.0 1.0 NaN
b 2.0 2.0 1.0
c 3.0 3.0 NaN
d NaN 4.0 2.0
df.loc['a',['one', 'three']] # pd.Seriesdf.columns, à leurs types df.dtypes, à l’index df.indexdf["four"] = df["one"] + df["two"], supprimer del df["one"]On peut construire une DataFrame à partir de dictionnaires, tableaux numpy, … ou de fichiers :
# Dictionnaire des colonnes
d = {
"one": pd.Series([1.0, 2.0, 3.0], index=["a", "b", "c"]),
"two": pd.Series([1.0, 2.0, 3.0, 4.0], index=["a", "b", "c", "d"]),
"three": pd.Series([1.0, 2.0 ], index=["b", "d"])
}
df = pd.DataFrame(d)
# Liste des lignes
df = pd.DataFrame([{"one": 1, "two": 2}, {"one": 5, "two": 10, "three": 20}])
# Fichier CSV
df = pd.read_csv("fichier.csv", delimiter=";")df.info(), df.describe(), df.head()df.describe(), (unique, top, freq) df.describe(include='category')datetime), des données catégorielles categories, des données numériques, il faut fixer les typesdef read_data(filepath: str):
df = pd.read_csv(filepath, delimiter=";")
return df
def fix_datatypes(df):
cat_columns = ['code_station', 'libelle_station', ...]
for c in cat_columns:
df[c] = df[c].astype('category')
df["date_observation"] = pd.to_datetime(df["date_observation"])
df = read_data("ecoulements.csv")
fix_datatypes(df)Important fixer les types des séries permet de profiter de toutes les fonctionnalités associées (e.g. catégories, temps)
Sur une dataframe, on peut :
df["Age"].median()min, max, mean, …) ou arbitraires df.agg({"Age": ["min", "max", "median", "skew"]})Les statistiques peuvent être calculées sur des sous-groupes formés par groupby:
titanic = pd.read_csv("data/titanic.csv")
# On peut regrouper les données par catégories et calculer
# des statistiques sur les sous-groupes
titanic = pd.read_csv("titanic.csv")
grouped = titanic[["Sex", "Pclass", "Age", "Fare"]].groupby(["Sex", "Pclass"])
print(grouped.size())
print(grouped.mean()) PassengerId Survived Pclass ... Fare Cabin Embarked
0 1 0 3 ... 7.2500 NaN S
1 2 1 1 ... 71.2833 C85 C
2 3 1 3 ... 7.9250 NaN S
Sex Pclass
female 1 94
2 76
3 144
male 1 122
2 108
3 347
dtype: int64
Age Fare
Sex Pclass
female 1 34.611765 106.125798
2 28.722973 21.970121
3 21.750000 16.118810
male 1 41.281386 67.226127
2 30.740707 19.741782
3 26.507589 12.661633Partant d’une représentation empilée (stacked), on peut réarranger les données avec la méthode pivot ou pivot_table (permet d’agréger) :
df = pd.DataFrame(
{
"A": ["one", "one", "two", "three"] * 6,
"B": ["bidule", "machin", "truc"] * 8,
"C": ["foo", "foo", "foo", "bar", "bar", "bar"] * 4,
"D": np.random.randn(24),
"E": np.random.randn(24),
"F": [datetime.datetime(2013, i, 1) for i in range(1, 13)]
+ [datetime.datetime(2013, i, 15) for i in range(1, 13)],
}
)
print(df)
pivoted = pd.pivot_table(df, values="D", index=["A", "B"], columns=["C"])
print(pivoted)
print(pivoted.loc[("one", "bidule"), "bar"]) A B C D E F
0 one bidule foo 0.029577 0.050984 2013-01-01
1 one machin foo -0.442099 -0.106008 2013-02-01
2 two truc foo 1.953053 1.265677 2013-03-01
3 three bidule bar -1.299982 0.762093 2013-04-01
4 one machin bar 0.652348 -0.323386 2013-05-01
5 one truc bar 1.433064 -1.818466 2013-06-01
6 two bidule foo 2.291547 -0.087507 2013-07-01
7 three machin foo -1.203084 -0.089323 2013-08-01
8 one truc foo 1.022026 -1.088463 2013-09-01
9 one bidule bar -0.433758 2.892209 2013-10-01
...
C bar foo
A B
one bidule 0.243642 -0.317265
machin -0.183342 -0.318656
truc 0.942341 1.991506
three bidule -0.641189 NaN
machin NaN -1.362425
truc -1.088678 NaN
two bidule NaN 1.272628
machin -0.686480 NaN
truc NaN 1.024224
0.24364165912866229pivot retourne une erreur en cas de doublons (moins flexible). pivot_table agrège les doublons (e.g. défaut : aggfunc='mean').
On peut joindre plusieurs dataframes par des clés, e.g. :
Ces tableaux peuvent être joints, par exemple pour lister les observations réalisées par un opérateur.
pd.merge dans les cheatsheets pandasPandas est interfacée avec matplotlib pour le tracé d’histogrammes (hist), nuages de points (scatter), séries (plot, même avec le temps !)
Les fonctions de tracé conduisent à des tracés indépendants pour des données groupées groupby.
Matplotlib : Numerical Python
Adapting the requirements laid out by John Hunter Matplotlib should:
Quelques concepts clés pour fixer les idées :
On suppose disposer de données \(x_i\) qui peuvent être étiquetées \(y_i\)
Apprentissage supervisé :
Etant donnés des paires \((x_i, y_i) \sim P_{X, Y}\), apprendre une fonction \(f_\theta\) (un prédicteur) qui minimise le risque réel :
\[ R_r(f) = \int_{X \ times Y} \mathcal{L}(y, f_\theta(x)) p_{X, Y}(x,y) dx dy \]
\[ R_e(f) = \sum_{i=0}^{N-1} \mathcal{L}(y_i, f_\theta(x_i)) \]
Question : comment prédire l’étiquette \(y\) associée à des \(x\) étant données des paires d’échantillons \((x_i, y_i)\)
Attention nous ne pourrons pas introduire tout les concepts liés au machine learning
Scikit-learn est une librairie python qui offre:
Le tout étant pipelinable et disposant d’une interface commune.
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
# Chargement des données
iris = load_iris()
X, y = iris.data, iris.target
# Construction d'un pli d'entrainement et un pli de test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Construction du prédicteur et entrainement
clf = make_pipeline(StandardScaler(), KNeighborsClassifier(3))
clf.fit(X_train, y_train)
# Evaluation du risque sur un pli de test
score = clf.score(X_test, y_test)
# Inférence sur le pli de test
y_test_pred = clf.transform(X_test)
Produced with quarto