Statistiques sous 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.

In [1]:
import matplotlib.pyplot
import pandas
import scipy.stats
import numpy

%matplotlib inline

Données

Nous allons travailler sur les données tips. Vous pouvez trouver des informations (ici). Voici comment lire ces données dans python avec read_csv() de pandas.

In [2]:
# Lecture d'un fichier texte
tips = pandas.read_csv("tips.csv", header = 0, sep = ",")
tips.head()
Out[2]:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4

Sur ces données, il est bien évidemment possible de voir quelques informations classiques.

In [3]:
type(tips)
Out[3]:
pandas.core.frame.DataFrame
In [4]:
# informations diverses
tips.shape
Out[4]:
(244, 7)
In [5]:
tips.count()
Out[5]:
total_bill    244
tip           244
sex           244
smoker        244
day           244
time          244
size          244
dtype: int64
In [6]:
tips.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 244 entries, 0 to 243
Data columns (total 7 columns):
total_bill    244 non-null float64
tip           244 non-null float64
sex           244 non-null object
smoker        244 non-null object
day           244 non-null object
time          244 non-null object
size          244 non-null int64
dtypes: float64(2), int64(1), object(4)
memory usage: 13.5+ KB
In [7]:
list(tips.columns)
Out[7]:
['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']
In [8]:
list(tips)
Out[8]:
['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size']

Manipulation de données

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 :

  • Restriction
  • Projection
  • Tri et limitation des résultats
  • Ajout de nouvelles variables (via des valeurs ou un calcul à partir des autres)
  • Agrégats
  • Jointures (qui ne seront pas vues ici)

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.

Restriction

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.

In [9]:
tips.query('total_bill > 48') # que les factures de plus de 48$
Out[9]:
total_bill tip sex smoker day time size
59 48.27 6.73 Male No Sat Dinner 4
156 48.17 5.00 Male No Sun Dinner 6
170 50.81 10.00 Male Yes Sat Dinner 3
212 48.33 9.00 Male No Sat Dinner 4
In [10]:
tips.query('day.isin(("Sat", "Sun"))') # que les factures ayant eu lieu un samedi ou un dimanche
Out[10]:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
... ... ... ... ... ... ... ...
238 35.83 4.67 Female No Sat Dinner 3
239 29.03 5.92 Male No Sat Dinner 3
240 27.18 2.00 Female Yes Sat Dinner 2
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2

163 rows × 7 columns

In [11]:
tips.query('size > 4 & sex == "Male"') # que les tables de plus de 4 convives et payées par un homme
Out[11]:
total_bill tip sex smoker day time size
141 34.30 6.7 Male No Thur Lunch 6
142 41.19 5.0 Male No Thur Lunch 5
156 48.17 5.0 Male No Sun Dinner 6
185 20.69 5.0 Male No Sun Dinner 5
187 30.46 2.0 Male Yes Sun Dinner 5
216 28.15 3.0 Male Yes Sat Dinner 5

Projection

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).

In [12]:
tips.filter(["sex", "total_bill"])
Out[12]:
sex total_bill
0 Female 16.99
1 Male 10.34
2 Male 21.01
3 Male 23.68
4 Female 24.59
... ... ...
239 Male 29.03
240 Female 27.18
241 Male 22.67
242 Male 17.82
243 Female 18.78

244 rows × 2 columns

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.

In [13]:
tips.filter(["sex", "smoker"]).drop_duplicates()
Out[13]:
sex smoker
0 Female No
1 Male No
56 Male Yes
67 Female Yes

Tri et limitation des résultats

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).

In [14]:
tips.sort_values(by = "total_bill")
Out[14]:
total_bill tip sex smoker day time size
67 3.07 1.00 Female Yes Sat Dinner 1
92 5.75 1.00 Female Yes Fri Dinner 2
111 7.25 1.00 Female No Sat Dinner 1
172 7.25 5.15 Male Yes Sun Dinner 2
149 7.51 2.00 Male No Thur Lunch 2
... ... ... ... ... ... ... ...
182 45.35 3.50 Male Yes Sun Dinner 3
156 48.17 5.00 Male No Sun Dinner 6
59 48.27 6.73 Male No Sat Dinner 4
212 48.33 9.00 Male No Sat Dinner 4
170 50.81 10.00 Male Yes Sat Dinner 3

244 rows × 7 columns

In [15]:
tips.sort_values(by = "total_bill", ascending = False)
Out[15]:
total_bill tip sex smoker day time size
170 50.81 10.00 Male Yes Sat Dinner 3
212 48.33 9.00 Male No Sat Dinner 4
59 48.27 6.73 Male No Sat Dinner 4
156 48.17 5.00 Male No Sun Dinner 6
182 45.35 3.50 Male Yes Sun Dinner 3
... ... ... ... ... ... ... ...
149 7.51 2.00 Male No Thur Lunch 2
111 7.25 1.00 Female No Sat Dinner 1
172 7.25 5.15 Male Yes Sun Dinner 2
92 5.75 1.00 Female Yes Fri Dinner 2
67 3.07 1.00 Female Yes Sat Dinner 1

244 rows × 7 columns

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.

In [16]:
tips.head(10) # 5 premières lignes par défaut
Out[16]:
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
5 25.29 4.71 Male No Sun Dinner 4
6 8.77 2.00 Male No Sun Dinner 2
7 26.88 3.12 Male No Sun Dinner 4
8 15.04 1.96 Male No Sun Dinner 2
9 14.78 3.23 Male No Sun Dinner 2
In [17]:
tips.tail(3) # 5 premières lignes par défaut
Out[17]:
total_bill tip sex smoker day time size
241 22.67 2.00 Male Yes Sat Dinner 2
242 17.82 1.75 Male No Sat Dinner 2
243 18.78 3.00 Female No Thur Dinner 2

Ajout de nouvelles variables

Il y a 2 possibilités ici :

  • à partir de valeurs déjà connues
  • à partir d'un calcul basé sur les autres variables

A partir de valeurs, soit vous en fournissez autant que de lignes, soit une seule qui sera donc dupliquée à toutes les lignes

In [18]:
tips['n_row'] = range(244)
tips['nouv'] = "nouvelle valeur"
tips.head()
Out[18]:
total_bill tip sex smoker day time size n_row nouv
0 16.99 1.01 Female No Sun Dinner 2 0 nouvelle valeur
1 10.34 1.66 Male No Sun Dinner 3 1 nouvelle valeur
2 21.01 3.50 Male No Sun Dinner 3 2 nouvelle valeur
3 23.68 3.31 Male No Sun Dinner 2 3 nouvelle valeur
4 24.59 3.61 Female No Sun Dinner 4 4 nouvelle valeur

Bien évidemment, on souhaite généralement faire un calcul à partir des autres variables. Ceci peut se faire avec la fonction assign().

In [19]:
# 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)) 
Out[19]:
total_bill tip sex smoker day time size n_row nouv per_person
0 16.99 1.01 Female No Sun Dinner 2 0 nouvelle valeur 8.49
1 10.34 1.66 Male No Sun Dinner 3 1 nouvelle valeur 3.45
2 21.01 3.50 Male No Sun Dinner 3 2 nouvelle valeur 7.00
3 23.68 3.31 Male No Sun Dinner 2 3 nouvelle valeur 11.84
4 24.59 3.61 Female No Sun Dinner 4 4 nouvelle valeur 6.15
... ... ... ... ... ... ... ... ... ... ...
239 29.03 5.92 Male No Sat Dinner 3 239 nouvelle valeur 9.68
240 27.18 2.00 Female Yes Sat Dinner 2 240 nouvelle valeur 13.59
241 22.67 2.00 Male Yes Sat Dinner 2 241 nouvelle valeur 11.34
242 17.82 1.75 Male No Sat Dinner 2 242 nouvelle valeur 8.91
243 18.78 3.00 Female No Thur Dinner 2 243 nouvelle valeur 9.39

244 rows × 10 columns

Agrégat

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()).

In [20]:
tips.filter(["total_bill", "tip", "size"]).aggregate(['count', "mean"])
Out[20]:
total_bill tip size
count 244.000000 244.000000 244.000000
mean 19.785943 2.998279 2.569672

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.

In [21]:
tips.filter(["sex", "total_bill", "tip", "size"]).groupby("sex").mean()
Out[21]:
total_bill tip size
sex
Female 18.056897 2.833448 2.459770
Male 20.744076 3.089618 2.630573

Si on a plusieurs variables dans le regroupement, le calcul se fait donc pour chaque couple de modalités de celles-ci.

In [22]:
tips.filter(["sex", "smoker", "total_bill", "tip", "size"]).groupby(["sex", "smoker"]).mean()
Out[22]:
total_bill tip size
sex smoker
Female No 18.105185 2.773519 2.592593
Yes 17.977879 2.931515 2.242424
Male No 19.791237 3.113402 2.711340
Yes 22.284500 3.051167 2.500000

Modification du format d'un data frame (reshaping)

Traditionnellement, en statistique, les tableaux sont présentés sous la forme individus décrits par des variables, comme le tableau tips par exemple.

In [23]:
tips.head()
Out[23]:
total_bill tip sex smoker day time size n_row nouv
0 16.99 1.01 Female No Sun Dinner 2 0 nouvelle valeur
1 10.34 1.66 Male No Sun Dinner 3 1 nouvelle valeur
2 21.01 3.50 Male No Sun Dinner 3 2 nouvelle valeur
3 23.68 3.31 Male No Sun Dinner 2 3 nouvelle valeur
4 24.59 3.61 Female No Sun Dinner 4 4 nouvelle valeur

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).

In [24]:
tips2 = tips.melt(id_vars = "n_row")
tips2
Out[24]:
n_row variable value
0 0 total_bill 16.99
1 1 total_bill 10.34
2 2 total_bill 21.01
3 3 total_bill 23.68
4 4 total_bill 24.59
... ... ... ...
1947 239 nouv nouvelle valeur
1948 240 nouv nouvelle valeur
1949 241 nouv nouvelle valeur
1950 242 nouv nouvelle valeur
1951 243 nouv nouvelle valeur

1952 rows × 3 columns

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.

In [25]:
pandas.pivot(tips2, index = "n_row", columns = "variable", values = "value")
Out[25]:
variable day nouv sex size smoker time tip total_bill
n_row
0 Sun nouvelle valeur Female 2 No Dinner 1.01 16.99
1 Sun nouvelle valeur Male 3 No Dinner 1.66 10.34
2 Sun nouvelle valeur Male 3 No Dinner 3.5 21.01
3 Sun nouvelle valeur Male 2 No Dinner 3.31 23.68
4 Sun nouvelle valeur Female 4 No Dinner 3.61 24.59
... ... ... ... ... ... ... ... ...
239 Sat nouvelle valeur Male 3 No Dinner 5.92 29.03
240 Sat nouvelle valeur Female 2 Yes Dinner 2 27.18
241 Sat nouvelle valeur Male 2 Yes Dinner 2 22.67
242 Sat nouvelle valeur Male 2 No Dinner 1.75 17.82
243 Thur nouvelle valeur Female 2 No Dinner 3 18.78

244 rows × 8 columns

Statistiques descriptives univariés

La fonction describe() permet de décrire toutes les variables quantitatives d'un jeu de données directement.

In [26]:
# résumé basique
tips.describe()
Out[26]:
total_bill tip size n_row
count 244.000000 244.000000 244.000000 244.000000
mean 19.785943 2.998279 2.569672 121.500000
std 8.902412 1.383638 0.951100 70.580923
min 3.070000 1.000000 1.000000 0.000000
25% 13.347500 2.000000 2.000000 60.750000
50% 17.795000 2.900000 2.000000 121.500000
75% 24.127500 3.562500 3.000000 182.250000
max 50.810000 10.000000 6.000000 243.000000
In [27]:
tips.describe().round(2)
Out[27]:
total_bill tip size n_row
count 244.00 244.00 244.00 244.00
mean 19.79 3.00 2.57 121.50
std 8.90 1.38 0.95 70.58
min 3.07 1.00 1.00 0.00
25% 13.35 2.00 2.00 60.75
50% 17.80 2.90 2.00 121.50
75% 24.13 3.56 3.00 182.25
max 50.81 10.00 6.00 243.00

Quantitative

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").

In [28]:
tips.total_bill.describe()
Out[28]:
count    244.000000
mean      19.785943
std        8.902412
min        3.070000
25%       13.347500
50%       17.795000
75%       24.127500
max       50.810000
Name: total_bill, dtype: float64
In [29]:
tips["total_bill"].describe()
Out[29]:
count    244.000000
mean      19.785943
std        8.902412
min        3.070000
25%       13.347500
50%       17.795000
75%       24.127500
max       50.810000
Name: total_bill, dtype: float64
In [30]:
tips.total_bill.mean()
Out[30]:
19.78594262295082
In [31]:
tips.total_bill.std()
Out[31]:
8.902411954856856
In [32]:
tips.total_bill.var()
Out[32]:
79.25293861397827
In [33]:
tips.total_bill.min()
Out[33]:
3.07
In [34]:
tips.total_bill.max()
Out[34]:
50.81
In [35]:
tips.total_bill.median()
Out[35]:
17.795
In [36]:
tips.total_bill.quantile([.01, .1, .9, .99])
Out[36]:
0.01     7.250
0.10    10.340
0.90    32.235
0.99    48.227
Name: total_bill, dtype: float64
In [37]:
scipy.stats.normaltest(tips.total_bill)
Out[37]:
NormaltestResult(statistic=45.11781912347332, pvalue=1.5951078766352608e-10)
In [38]:
scipy.stats.shapiro(tips.total_bill)
Out[38]:
(0.9197188019752502, 3.3245434183371003e-10)

Histogramme

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.

In [39]:
tips.plot.hist()
Out[39]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb97cd76d8>
In [40]:
tips.total_bill.hist()
Out[40]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb95c0cb00>
In [41]:
tips.total_bill.hist(bins = 20)
Out[41]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb954a4c88>
In [42]:
tips.total_bill.plot(kind = "hist")
Out[42]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb954345c0>
In [43]:
tips.total_bill.plot(kind = "hist", density = True)
Out[43]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb97cd70f0>
In [44]:
tips.total_bill.plot(kind = "kde")
Out[44]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb9532de80>

Pour avoir la densité et l'histogramme sur le même graphique, il est nécessaire de compiler les deux lignes suivantes ensemble.

In [45]:
tips.total_bill.plot(kind = "hist", normed = True, color = "lightgrey")
tips.total_bill.plot(kind = "kde")
/home/jollois/.local/lib/python3.6/site-packages/pandas/plotting/_matplotlib/hist.py:62: MatplotlibDeprecationWarning: 
The 'normed' kwarg was deprecated in Matplotlib 2.1 and will be removed in 3.1. Use 'density' instead.
  n, bins, patches = ax.hist(y, bins=bins, bottom=bottom, **kwds)
Out[45]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb952f32b0>

Boîtes à moustaches

Enfin, pour les boîtes à moustaches, il faut passer par le DataFrame pour l'afficher, et choisir une variable spécifiquement éventuellement.

In [46]:
tips.boxplot()
Out[46]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb9528f048>
In [47]:
tips.boxplot(column = "total_bill")
Out[47]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb95198748>
In [48]:
tips.boxplot(column = "total_bill", grid = False)
Out[48]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb9518be10>

Qualitative

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.

In [49]:
tips.sex.describe()
Out[49]:
count      244
unique       2
top       Male
freq       157
Name: sex, dtype: object
In [50]:
tips.sex.unique()
Out[50]:
array(['Female', 'Male'], dtype=object)
In [51]:
tips.sex.value_counts()
Out[51]:
Male      157
Female     87
Name: sex, dtype: int64
In [52]:
pandas.crosstab(tips.sex, "freq")
Out[52]:
col_0 freq
sex
Female 87
Male 157
In [53]:
pandas.crosstab(tips.sex, "freq", normalize=True)
Out[53]:
col_0 freq
sex
Female 0.356557
Male 0.643443
In [54]:
t = pandas.crosstab(tips.sex, "freq")
scipy.stats.chisquare(t)
Out[54]:
Power_divergenceResult(statistic=array([20.08196721]), pvalue=array([7.41929371e-06]))

Diagramme en barres

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.

In [55]:
t = pandas.crosstab(tips.sex, "freq")
t.plot.bar()
Out[55]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb95093470>
In [56]:
t.plot(kind = "bar")
Out[56]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb95059898>
In [57]:
t = pandas.crosstab(tips.sex, "freq", normalize=True)
t.plot(kind = "bar")
Out[57]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb94fe1048>
In [58]:
(t * 100).plot(kind = "bar")
Out[58]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb94fc95f8>

Diagramme circulaire

Et pour un diagramme circulaire, seul le tableau des effectifs produit par value_counts() nous permet de le réaliser.

In [59]:
t = pandas.crosstab(tips.sex, "freq")
t.plot.pie(subplots=True, figsize = (6, 6))
Out[59]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94f312b0>],
      dtype=object)

Statistiques descriptives bivariées

Quantitative - quantitative

In [60]:
tips.corr()
Out[60]:
total_bill tip size n_row
total_bill 1.000000 0.675734 0.598315 0.044526
tip 0.675734 1.000000 0.489299 -0.026709
size 0.598315 0.489299 1.000000 0.008061
n_row 0.044526 -0.026709 0.008061 1.000000
In [61]:
tips.total_bill.corr(tips.tip)
Out[61]:
0.6757341092113641
In [62]:
tips.total_bill.cov(tips.tip)
Out[62]:
8.323501629224854
In [63]:
scipy.stats.pearsonr(tips.total_bill, tips.tip)
Out[63]:
(0.6757341092113647, 6.6924706468630016e-34)
In [64]:
scipy.stats.kendalltau(tips.total_bill, tips.tip)
Out[64]:
KendalltauResult(correlation=0.517180972142381, pvalue=2.4455728480214792e-32)

Nuage de points

In [65]:
tips.plot.scatter("total_bill", "tip")
Out[65]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb97d29f60>
In [66]:
pandas.plotting.scatter_matrix(tips)
Out[66]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94e7b6a0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94e1ab00>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94dd8080>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94e094a8>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94dbaa20>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94d6bfd0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94d285c0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94cdaba8>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94cdabe0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94cca710>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94c7acc0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94c382b0>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94be7860>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94b9de10>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94b57400>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb94b8a9b0>]],
      dtype=object)

Qualitative - qualitative

In [67]:
pandas.crosstab(tips.sex, tips.smoker)
Out[67]:
smoker No Yes
sex
Female 54 33
Male 97 60
In [68]:
pandas.crosstab(tips.sex, tips.smoker, margins=True)
Out[68]:
smoker No Yes All
sex
Female 54 33 87
Male 97 60 157
All 151 93 244
In [69]:
pandas.crosstab(tips.sex, tips.smoker, normalize = True)
Out[69]:
smoker No Yes
sex
Female 0.221311 0.135246
Male 0.397541 0.245902
In [70]:
pandas.crosstab(tips.sex, tips.smoker, normalize = "index")
Out[70]:
smoker No Yes
sex
Female 0.620690 0.379310
Male 0.617834 0.382166
In [71]:
pandas.crosstab(tips.sex, tips.smoker, normalize = "index", margins=True)
Out[71]:
smoker No Yes
sex
Female 0.620690 0.379310
Male 0.617834 0.382166
All 0.618852 0.381148
In [72]:
pandas.crosstab(tips.sex, tips.smoker, normalize = "columns")
Out[72]:
smoker No Yes
sex
Female 0.357616 0.354839
Male 0.642384 0.645161
In [73]:
pandas.crosstab(tips.sex, tips.smoker, normalize = "columns", margins=True)
Out[73]:
smoker No Yes All
sex
Female 0.357616 0.354839 0.356557
Male 0.642384 0.645161 0.643443
In [74]:
t = pandas.crosstab(tips.sex, tips.smoker)
scipy.stats.chi2_contingency(t)
Out[74]:
(0.008763290531773594, 0.925417020494423, 1, array([[53.84016393, 33.15983607],
        [97.15983607, 59.84016393]]))

Diagramme en barres

In [75]:
t = pandas.crosstab(tips.sex, tips.smoker)
t.plot.bar()
Out[75]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb97d1b828>
In [76]:
t = pandas.crosstab(tips.sex, tips.smoker, normalize=True)
t.plot.bar()
Out[76]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb941536d8>
In [77]:
t = pandas.crosstab(tips.sex, tips.smoker, normalize="index")
t.plot.bar(stacked=True)
Out[77]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb94112748>
In [78]:
t = pandas.crosstab(tips.sex, tips.smoker)
t.plot.pie(subplots=True, figsize = (12, 6))
Out[78]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb940acf28>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb9405c550>],
      dtype=object)

Qualitative - quantitative

In [79]:
tips.groupby("sex").mean()
Out[79]:
total_bill tip size n_row
sex
Female 18.056897 2.833448 2.459770 128.080460
Male 20.744076 3.089618 2.630573 117.853503
In [80]:
tips.groupby("sex")["total_bill"].agg([numpy.mean, numpy.std, numpy.median, numpy.min, numpy.max])
Out[80]:
mean std median amin amax
sex
Female 18.056897 8.009209 16.40 3.07 44.30
Male 20.744076 9.246469 18.35 7.25 50.81
In [81]:
billFemale = tips.total_bill[tips.sex == "Female"]
billMale = tips.total_bill[tips.sex == "Male"]
scipy.stats.ttest_ind(billFemale, billMale)
Out[81]:
Ttest_indResult(statistic=-2.2777940289803134, pvalue=0.0236116668468594)
In [82]:
billGrouped = [tips.total_bill[tips.sex == s] for s in list(tips.sex.unique())]
scipy.stats.f_oneway(*billGrouped)
Out[82]:
F_onewayResult(statistic=5.188345638458361, pvalue=0.023611666846859697)
In [83]:
tips.hist(column = "total_bill", by = "sex")
Out[83]:
array([<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb8ee31dd8>,
       <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb8ee64eb8>],
      dtype=object)
In [84]:
tips.boxplot(by = "sex")
Out[84]:
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb9402dc18>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb8eef8c18>],
       [<matplotlib.axes._subplots.AxesSubplot object at 0x7fdb8eeab9e8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x7fdb8edf0828>]],
      dtype=object)
In [85]:
tips.boxplot(column = "total_bill", by = "sex") 
Out[85]:
<matplotlib.axes._subplots.AxesSubplot at 0x7fdb8ef4c6a0>

Exercices

Worldwide Governance Indicators (WGI)

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 :

  • Reconstruire un tableau avec en ligne les pays (on souhaite avoir le nom et le code) et en colonnes les 6 variables (en simplifiant les noms).
  • Donner les informations de la France
  • Donner les informations de 5 pays européens
  • Trouver les 10 pays ayant les valeurs les plus hautes pour Control of Corruption
  • Donner les valeurs moyennes, minimales et maximales de chaque indicateurs
  • Donner les pays avec les valeurs minimales pour chaque indicateur (en plusieurs commandes)

Diamonds

A partir du fichier diamonds.csv (voir l'aide ici), analyser les données suivant le déroulement classique

  1. Description de chaque variable
  2. Recherche des liens entre le prix (price) et les autres variables

Pour cela, écrire un notebook propre, avec du texte clair, du code et des graphiques le plus propre possible.

In [ ]: