Python
¶Nous allons utiliser dans ce TP le module pandas
facilitant la manipulation de données avec Python. Nous allons aussi utiliser les modules matplotlib
et scipy
.
Il faut tout d'abord importer ces modules. La dernière ligne permettra de voir le résultat des graphiques dans le document.
import matplotlib.pyplot
import pandas
import scipy.stats
import numpy
%matplotlib inline
# Lecture d'un fichier texte
tips = pandas.read_csv("tips.csv", header = 0, sep = ",")
tips.head()
Sur ces données, il est bien évidemment possible de voir quelques informations classiques.
type(tips)
# informations diverses
tips.shape
tips.count()
tips.info()
list(tips.columns)
list(tips)
Une fois qu'on a des données, la première chose qu'on souhaite savoir faire souvent, est de pouvoir manipuler ces données; C'est-à-dire réaliser les opérations classiques en bases de données, à savoir :
Il y a d'autres opérations, spécifiques à Python, qu'on ne verra pas ici. La dernière opération que l'on verra est la modification de la forme du tableau de données.
Note Bene : certaines fonctions renvoient un nouvel objet qu'il faudra donc stocker dans une variable (nouvelle ou la même). Par contre, d'autres fonctions modifient directement l'objet en question.
Première étape essentiel, cela consiste à sélectionner un certain nombre de lignes de la table, selon une condition sur les valeurs des variables. Il exite pour cela la fonction query()
prenant en paramètre une chaîne de caractères contenant la condition à appliquer. Voici quelques exemples de condition. Il y a bien évidemment beaucoup d'autres fonctions existantes, en particuliers pour les chaînes.
tips.query('total_bill > 48') # que les factures de plus de 48$
tips.query('day.isin(("Sat", "Sun"))') # que les factures ayant eu lieu un samedi ou un dimanche
tips.query('size > 4 & sex == "Male"') # que les tables de plus de 4 convives et payées par un homme
Deuxième étape, celle-ci consiste tout simple à sélectionner certaines colonnes de la tables. En python, on utilise la fonction filter()
. Il faut noter que celle-ci peut aussi fonctionner sur les lignes (quand celles-ci ont un index - pas vu ici).
tips.filter(["sex", "total_bill"])
Quand on fait ce genre d'opérations, il est courant que nous nous retrouvions avec des lignes identiques. Pour supprimer les doublons, nous utilisons la fonction drop_duplicates()
sur le résultat.
tips.filter(["sex", "smoker"]).drop_duplicates()
Pour le tri, il existe la fonction sort_values()
, dans laquelle on indique la ou les variables à utiliser pour le tri. Si on veut un tri descendant, on modifie la valeur du paramètre ascending
(True
par défaut).
tips.sort_values(by = "total_bill")
tips.sort_values(by = "total_bill", ascending = False)
Pour se limiter aux premières lignes (respectivement les dernières), on utilise la fonction head()
(resp. tail()
), qui affiche par défaut 5 lignes. Cette valeur est bien évidemment modifiable, comme vu ci-après.
tips.head(10) # 5 premières lignes par défaut
tips.tail(3) # 5 premières lignes par défaut
Il y a 2 possibilités ici :
A partir de valeurs, soit vous en fournissez autant que de lignes, soit une seule qui sera donc dupliquée à toutes les lignes
tips['n_row'] = range(244)
tips['nouv'] = "nouvelle valeur"
tips.head()
Bien évidemment, on souhaite généralement faire un calcul à partir des autres variables. Ceci peut se faire avec la fonction assign()
.
# attention ici, l.size fait référence à la taille de l, car c'est un mot clé de python
tips.assign(per_person = lambda l: round(l.total_bill / l['size'], 2))
Le calcul d'un agrégat permet de calculer une statistique de base (dénombrement, somme, moyenne, minimum, maximum - rarement autre chose) sur un tableau de données. On peut soit calculer globalement, soit pour chaque modalité d'une variable (voire chaque couple de modalités de plusieurs variables).
Pour le faire globalement, on utilise la fonction aggregate()
(ou agg()
).
tips.filter(["total_bill", "tip", "size"]).aggregate(['count', "mean"])
Pour le faire pour chaque modalité d'une variable, on utilise la fonction groupby()
en plus. Si on ne réalise qu'un seul calcul, on a directement les fonctions associées.
tips.filter(["sex", "total_bill", "tip", "size"]).groupby("sex").mean()
Si on a plusieurs variables dans le regroupement, le calcul se fait donc pour chaque couple de modalités de celles-ci.
tips.filter(["sex", "smoker", "total_bill", "tip", "size"]).groupby(["sex", "smoker"]).mean()
Traditionnellement, en statistique, les tableaux sont présentés sous la forme individus décrits par des variables, comme le tableau tips
par exemple.
tips.head()
Parfois, il est utile (voire nécessaire) de modifier, via une pseudo-rotation, en un tableau avec une colonne (ou plusieurs) indiquant l'individu concerné, une colonne indiquant la variable et une autre avec la valeur de celle-ci. Il est aussi possible d'avoir les données directement comme ceci (comme vous le verrez plus loin). Pour cela, nous utilisons la fonction melt()
, dans laquelle on précise quel est l'identifiant de chaque ligne (celui-ci peut être sur plusieurs colonnes).
tips2 = tips.melt(id_vars = "n_row")
tips2
Pour revenir à une présentation classique, il faut donc faire la aussi une pseudo-rotation, mais inverse cette fois-ci. Pour cela, nous utilisons la fonction pivot()
, comme ci-dessous.
pandas.pivot(tips2, index = "n_row", columns = "variable", values = "value")
La fonction describe()
permet de décrire toutes les variables quantitatives d'un jeu de données directement.
# résumé basique
tips.describe()
tips.describe().round(2)
Il est possible de sélectionner les variables soit via les crochets []
, soit par un point .
.
Les fonctions ci-dessous permettent de décrire une variable quantitative (ici "total_bill"
).
tips.total_bill.describe()
tips["total_bill"].describe()
tips.total_bill.mean()
tips.total_bill.std()
tips.total_bill.var()
tips.total_bill.min()
tips.total_bill.max()
tips.total_bill.median()
tips.total_bill.quantile([.01, .1, .9, .99])
scipy.stats.normaltest(tips.total_bill)
scipy.stats.shapiro(tips.total_bill)
Pour représenter graphiquement cette variable, pandas
met à disposition (via le module matplotlib
utilisé par pandas
) des fonctions graphiques.
Pour réaliser un histogramme, nous utilisons la fonction hist()
. Celle-ci peut prendre des options. La fonction plot()
avec le paramètre kind
avec la valeur "hist"
revient au même résultat.
tips.plot.hist()
tips.total_bill.hist()
tips.total_bill.hist(bins = 20)
tips.total_bill.plot(kind = "hist")
tips.total_bill.plot(kind = "hist", density = True)
tips.total_bill.plot(kind = "kde")
Pour avoir la densité et l'histogramme sur le même graphique, il est nécessaire de compiler les deux lignes suivantes ensemble.
tips.total_bill.plot(kind = "hist", normed = True, color = "lightgrey")
tips.total_bill.plot(kind = "kde")
Enfin, pour les boîtes à moustaches, il faut passer par le DataFrame
pour l'afficher, et choisir une variable spécifiquement éventuellement.
tips.boxplot()
tips.boxplot(column = "total_bill")
tips.boxplot(column = "total_bill", grid = False)
Pour les variables qualitatives, il y a plusieurs façons de faire pour obtenir la table d'occurences (ou des effectifs), ainsi que la table des proportions des modalités.
tips.sex.describe()
tips.sex.unique()
tips.sex.value_counts()
pandas.crosstab(tips.sex, "freq")
pandas.crosstab(tips.sex, "freq", normalize=True)
t = pandas.crosstab(tips.sex, "freq")
scipy.stats.chisquare(t)
Ensuite, pour réaliser un diagramme en barres, nous utilisons le type "bar"
pour plot()
. Les calculs de proportions précédents nous permettent d'afficher une représentation des proportions plutôt que des effectifs.
t = pandas.crosstab(tips.sex, "freq")
t.plot.bar()
t.plot(kind = "bar")
t = pandas.crosstab(tips.sex, "freq", normalize=True)
t.plot(kind = "bar")
(t * 100).plot(kind = "bar")
Et pour un diagramme circulaire, seul le tableau des effectifs produit par value_counts()
nous permet de le réaliser.
t = pandas.crosstab(tips.sex, "freq")
t.plot.pie(subplots=True, figsize = (6, 6))
tips.corr()
tips.total_bill.corr(tips.tip)
tips.total_bill.cov(tips.tip)
scipy.stats.pearsonr(tips.total_bill, tips.tip)
scipy.stats.kendalltau(tips.total_bill, tips.tip)
tips.plot.scatter("total_bill", "tip")
pandas.plotting.scatter_matrix(tips)
pandas.crosstab(tips.sex, tips.smoker)
pandas.crosstab(tips.sex, tips.smoker, margins=True)
pandas.crosstab(tips.sex, tips.smoker, normalize = True)
pandas.crosstab(tips.sex, tips.smoker, normalize = "index")
pandas.crosstab(tips.sex, tips.smoker, normalize = "index", margins=True)
pandas.crosstab(tips.sex, tips.smoker, normalize = "columns")
pandas.crosstab(tips.sex, tips.smoker, normalize = "columns", margins=True)
t = pandas.crosstab(tips.sex, tips.smoker)
scipy.stats.chi2_contingency(t)
t = pandas.crosstab(tips.sex, tips.smoker)
t.plot.bar()
t = pandas.crosstab(tips.sex, tips.smoker, normalize=True)
t.plot.bar()
t = pandas.crosstab(tips.sex, tips.smoker, normalize="index")
t.plot.bar(stacked=True)
t = pandas.crosstab(tips.sex, tips.smoker)
t.plot.pie(subplots=True, figsize = (12, 6))
tips.groupby("sex").mean()
tips.groupby("sex")["total_bill"].agg([numpy.mean, numpy.std, numpy.median, numpy.min, numpy.max])
billFemale = tips.total_bill[tips.sex == "Female"]
billMale = tips.total_bill[tips.sex == "Male"]
scipy.stats.ttest_ind(billFemale, billMale)
billGrouped = [tips.total_bill[tips.sex == s] for s in list(tips.sex.unique())]
scipy.stats.f_oneway(*billGrouped)
tips.hist(column = "total_bill", by = "sex")
tips.boxplot(by = "sex")
tips.boxplot(column = "total_bill", by = "sex")
A partir du fichier WGI_Data.csv
, qui donne certains indicateurs sur la gouvernance des pays (plus d'infos sur cette page), réaliser les étapes suivantes :
A partir du fichier diamonds.csv
(voir l'aide ici), analyser les données suivant le déroulement classique
price
) et les autres variablesPour cela, écrire un notebook propre, avec du texte clair, du code et des graphiques le plus propre possible.