import numpy as np
import pandas as pd
print(pd.__version__)
1.4.2
series1 = pd.Series([10, 20, 30, 40])
print(series1)
0 10 1 20 2 30 3 40 dtype: int64
l=series1.to_list()
print(l)
[10, 20, 30, 40]
a=np.arange(10,15)
series2 = pd.Series(a, index = [1, 3, 5, 7, 9])
print(series2)
1 10 3 11 5 12 7 13 9 14 dtype: int64
l=series2.to_list()
print(l)
[10, 11, 12, 13, 14]
# on a une "colonne" d'indidus identifiés par leur nom (<=> id)
prenoms = ['liz', 'bob', 'bill', 'eve']
# on crée des colonnes à ajouter à cette colonne d'individu
age = pd.Series([25, 30, 35, 40], index = prenoms)
taille = pd.Series([160, 175, 170, 180], index = prenoms)
sexe = pd.Series(list('bhff'), index = prenoms)
#Les sequences doivent toutes avoir la même size sinon ça bogue
print(len(prenoms), len(age), len(taille), len(sexe))
4 4 4 4
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
# On récupère une table excel :
#
# age taille sexe
# liz 25 160 f
# bob 30 175 h
# bill 35 170 h
# eve 40 180 f
df
age | taille | sexe | |
---|---|---|---|
liz | 25 | 160 | b |
bob | 30 | 175 | h |
bill | 35 | 170 | f |
eve | 40 | 180 | f |
## Création plus subtile : NaN et colonne constante
age = pd.Series([30, 20, 50], index=['alice', 'bob', 'julie'])
height = pd.Series([150, 170, 168], index=['alice', 'marc', 'julie'])
df2 = pd.DataFrame({'age': age, 'height': height, 'city': 'Nice'})
print(df2)
age height city alice 30.0 150.0 Nice bob 20.0 NaN Nice julie 50.0 168.0 Nice marc NaN 170.0 Nice
# on recharge pour éviter les ennuis
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
print(df.index) # index des lignes
print(df.columns) # index des colonnes
print(df.values) # toutes les valeurs
print(df.shape) # format du tableau numpy
print(type(df.values))
Index(['alice', 'bill', 'bob', 'eve', 'julie', 'liz'], dtype='object') Index(['age', 'taille', 'sexe'], dtype='object') [[30.0 nan nan] [nan 170.0 'f'] [20.0 175.0 'h'] [nan 180.0 'f'] [50.0 nan nan] [nan 160.0 'b']] (6, 3) <class 'numpy.ndarray'>
print(df.index[0]) #liz
# df.index[0]="coucou" : bogue ! c'est immutable
print(df.index*2) # opération vectorisé sur un tableau numpy
a=np.array([1,2]).reshape(2,1)
df.index*a
alice Index(['alicealice', 'billbill', 'bobbob', 'eveeve', 'juliejulie', 'lizliz'], dtype='object')
Index([('alice', 'bill', 'bob', 'eve', 'julie', 'liz'), ('alicealice', 'billbill', 'bobbob', 'eveeve', 'juliejulie', 'lizliz')], dtype='object')
df.head(2)
age | taille | sexe | |
---|---|---|---|
alice | 30.0 | NaN | NaN |
bill | NaN | 170.0 | f |
df.tail(2)
age | taille | sexe | |
---|---|---|---|
julie | 50.0 | NaN | NaN |
liz | NaN | 160.0 | b |
df
age | taille | sexe | |
---|---|---|---|
alice | 30.0 | NaN | NaN |
bill | NaN | 170.0 | f |
bob | 20.0 | 175.0 | h |
eve | NaN | 180.0 | f |
julie | 50.0 | NaN | NaN |
liz | NaN | 160.0 | b |
df.describe()
age | taille | |
---|---|---|
count | 3.000000 | 4.000000 |
mean | 33.333333 | 171.250000 |
std | 15.275252 | 8.539126 |
min | 20.000000 | 160.000000 |
25% | 25.000000 | 167.500000 |
50% | 30.000000 | 172.500000 |
75% | 40.000000 | 176.250000 |
max | 50.000000 | 180.000000 |
df.describe(include='all')
# unique : nombre de valeurs possibles
# freq : frequence la plus élevée
# top : valeur de la fréquence la plus élevée
age | taille | sexe | |
---|---|---|---|
count | 3.000000 | 4.000000 | 4 |
unique | NaN | NaN | 3 |
top | NaN | NaN | f |
freq | NaN | NaN | 2 |
mean | 33.333333 | 171.250000 | NaN |
std | 15.275252 | 8.539126 | NaN |
min | 20.000000 | 160.000000 | NaN |
25% | 25.000000 | 167.500000 | NaN |
50% | 30.000000 | 172.500000 | NaN |
75% | 40.000000 | 176.250000 | NaN |
max | 50.000000 | 180.000000 | NaN |
df.T
alice | bill | bob | eve | julie | liz | |
---|---|---|---|---|---|---|
age | 30.0 | NaN | 20.0 | NaN | 50.0 | NaN |
taille | NaN | 170.0 | 175.0 | 180.0 | NaN | 160.0 |
sexe | NaN | f | h | f | NaN | b |
# on recharge pour éviter les ennuis
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
df
age | taille | sexe | |
---|---|---|---|
alice | 30.0 | NaN | NaN |
bill | NaN | 170.0 | f |
bob | 20.0 | 175.0 | h |
eve | NaN | 180.0 | f |
julie | 50.0 | NaN | NaN |
liz | NaN | 160.0 | b |
# on recharge pour éviter les ennuis
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
df
age | taille | sexe | |
---|---|---|---|
alice | 30.0 | NaN | NaN |
bill | NaN | 170.0 | f |
bob | 20.0 | 175.0 | h |
eve | NaN | 180.0 | f |
julie | 50.0 | NaN | NaN |
liz | NaN | 160.0 | b |
# avec un loc : toute la ligne
a=df.loc['liz'] # la ligne de liz : accès par l'index nommée (le label de ligne)
print(a)
print('## taille: ', a['taille'])
print(a[0])
age NaN taille 160.0 sexe b Name: liz, dtype: object ## taille: 160.0 nan
# Avec un loc : ligne et colonne : le bon usage
a=df.loc['liz', 'taille'] # la ligne de liz et son age : l
print(a)
print(type(a))
160.0 <class 'numpy.float64'>
print(df)
df.iloc[1] # accès par l'index numéroté automatique : on perd l'index nommé
age taille sexe alice 30.0 NaN NaN bill NaN 170.0 f bob 20.0 175.0 h eve NaN 180.0 f julie 50.0 NaN NaN liz NaN 160.0 b
age NaN taille 170.0 sexe f Name: bill, dtype: object
df.loc['bill':'eve'] # les lignes de bill à eve compris
age | taille | sexe | |
---|---|---|---|
bill | NaN | 170.0 | f |
bob | 20.0 | 175.0 | h |
eve | NaN | 180.0 | f |
df[['taille', 'age']]
taille | age | |
---|---|---|
alice | NaN | 30.0 |
bill | 170.0 | NaN |
bob | 175.0 | 20.0 |
eve | 180.0 | NaN |
julie | NaN | 50.0 |
liz | 160.0 | NaN |
print(df.loc[:,'taille']) # slicing
print(type(df.loc[:,'taille']))
alice NaN bill 170.0 bob 175.0 eve 180.0 julie NaN liz 160.0 Name: taille, dtype: float64 <class 'pandas.core.series.Series'>
df.loc[:,'taille'].index
Index(['alice', 'bill', 'bob', 'eve', 'julie', 'liz'], dtype='object')
df.loc[:,'taille'].values
array([ nan, 170., 175., 180., nan, 160.])
df.loc['bill':'eve','taille':] # slicing
taille | sexe | |
---|---|---|
bill | 170.0 | f |
bob | 175.0 | h |
eve | 180.0 | f |
df.loc['bill'::2,'taille'] # slicing
bill 170.0 eve 180.0 liz 160.0 Name: taille, dtype: float64
print(df.loc[:,'age']<32) # slicing + comparaison vectorisée : on récupère un masque tableau de booléens
df.loc[df.loc[:,'age']<32 ] # le masque permet de filtrer le tableau de départ
alice True bill False bob True eve False julie False liz False Name: age, dtype: bool
age | taille | sexe | |
---|---|---|---|
alice | 30.0 | NaN | NaN |
bob | 20.0 | 175.0 | h |
# on recharge pour éviter les ennuis
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
# Quel est la moyenne de tous les âges
# A noter que le mean laisser passer les NaN
c = df.loc[:, 'age']
m = c.mean()
print(type(c))
print(c)
print(f"L'âge moyen est de {m:.1f} ans.") # f string python
<class 'pandas.core.series.Series'> alice 30.0 bill NaN bob 20.0 eve NaN julie 50.0 liz NaN Name: age, dtype: float64 L'âge moyen est de 33.3 ans.
print(df)
df=df.reset_index() # prend l'index et le met dans une colonne et ajoute un id numéroté
df
age taille sexe alice 30.0 NaN NaN bill NaN 170.0 f bob 20.0 175.0 h eve NaN 180.0 f julie 50.0 NaN NaN liz NaN 160.0 b
index | age | taille | sexe | |
---|---|---|---|---|
0 | alice | 30.0 | NaN | NaN |
1 | bill | NaN | 170.0 | f |
2 | bob | 20.0 | 175.0 | h |
3 | eve | NaN | 180.0 | f |
4 | julie | 50.0 | NaN | NaN |
5 | liz | NaN | 160.0 | b |
df = df.rename(columns={'index': 'prenom'})
df
prenom | age | taille | sexe | |
---|---|---|---|---|
0 | alice | 30.0 | NaN | NaN |
1 | bill | NaN | 170.0 | f |
2 | bob | 20.0 | 175.0 | h |
3 | eve | NaN | 180.0 | f |
4 | julie | 50.0 | NaN | NaN |
5 | liz | NaN | 160.0 | b |
df = df.rename(columns={'taille': 'mesure'})
df
prenom | age | mesure | sexe | |
---|---|---|---|---|
0 | alice | 30.0 | NaN | NaN |
1 | bill | NaN | 170.0 | f |
2 | bob | 20.0 | 175.0 | h |
3 | eve | NaN | 180.0 | f |
4 | julie | 50.0 | NaN | NaN |
5 | liz | NaN | 160.0 | b |
df = df.set_index('age') # on met comme index la colonne des âges
df
prenom | mesure | sexe | |
---|---|---|---|
age | |||
30.0 | alice | NaN | NaN |
NaN | bill | 170.0 | f |
20.0 | bob | 175.0 | h |
NaN | eve | 180.0 | f |
50.0 | julie | NaN | NaN |
NaN | liz | 160.0 | b |
df.head(2)
prenom | mesure | sexe | |
---|---|---|---|
age | |||
30.0 | alice | NaN | NaN |
NaN | bill | 170.0 | f |
print(age)
print(taille)
print(sexe)
df = pd.DataFrame({'age': age, 'taille': taille, 'sexe': sexe})
# on utilise une écriture avec enchainement d'étapes : c'est plus lisible
# il faut que les méthodes retournent un dataframe
df = (df.reset_index() # on reste l'index : le prenom passe en colonne
.rename(columns={'index': 'prenom'}) # on renomme l'index en prenom
.set_index('age')) # on met l'age comme index
df
alice 30 bob 20 julie 50 dtype: int64 liz 160 bob 175 bill 170 eve 180 dtype: int64 liz b bob h bill f eve f dtype: object
prenom | taille | sexe | |
---|---|---|---|
age | |||
30.0 | alice | NaN | NaN |
NaN | bill | 170.0 | f |
20.0 | bob | 175.0 | h |
NaN | eve | 180.0 | f |
50.0 | julie | NaN | NaN |
NaN | liz | 160.0 | b |
print(df.iloc[0])
print(type(df.iloc[0]))
prenom alice taille NaN sexe NaN Name: 30.0, dtype: object <class 'pandas.core.series.Series'>
print(df.iloc[0:3])
print(type(df.iloc[0:3]))
prenom taille sexe age 30.0 alice NaN NaN NaN bill 170.0 f 20.0 bob 175.0 h <class 'pandas.core.frame.DataFrame'>
df.loc[:,:]
prenom | taille | sexe | |
---|---|---|---|
age | |||
30.0 | alice | NaN | NaN |
NaN | bill | 170.0 | f |
20.0 | bob | 175.0 | h |
NaN | eve | 180.0 | f |
50.0 | julie | NaN | NaN |
NaN | liz | 160.0 | b |
df.loc[:,'taille'].mean()
171.25
# Création de dataframes par index et colums
## Exemple 1
a = np.random.randint(1, 20, 9).reshape(3, 3)
p = pd.DataFrame(a, index=['a', 'b', 'c'], columns=['x', 'y', 'z'])
print(p)
x y z a 3 7 12 b 3 16 3 c 10 9 17
## Exemple 2
df1 = pd.DataFrame(
np.ones((2, 2)),
index=list('ab'),
columns=list('xy')
)
df1
x | y | |
---|---|---|
a | 1.0 | 1.0 |
b | 1.0 | 1.0 |
df2 = pd.DataFrame(
np.arange(1,5).reshape(2,2),
index=list('ac'),
columns=list('xz'))
df2
x | z | |
---|---|---|
a | 1 | 2 |
c | 3 | 4 |
# On a 2 dataframes avec x et a en commun.
# L'addition crée un dataframe avec toutes les lignes et toutes les colonnnes
# L'addtion se fait si les valeurs existent dans les deux dataframes de départ
df1+df2
x | y | z | |
---|---|---|---|
a | 2.0 | NaN | NaN |
b | NaN | NaN | NaN |
c | NaN | NaN | NaN |
# On passe la fonction add pour faire l'addition
# On met une valeur par défaut à 0 pour les NaN
# La valeur par défaut s'applique si on a au moins une valeur concrète
df1.add(df2, fill_value=0)
x | y | z | |
---|---|---|---|
a | 2.0 | 1.0 | 2.0 |
b | 1.0 | 1.0 | NaN |
c | 3.0 | NaN | 4.0 |
df3=df1.add(df2, fill_value=0).fillna(-1)
df3
x | y | z | |
---|---|---|---|
a | 2.0 | 1.0 | 2.0 |
b | 1.0 | 1.0 | -1.0 |
c | 3.0 | -1.0 | 4.0 |
df1.add(df2, fill_value=0).dropna()
x | y | z | |
---|---|---|---|
a | 2.0 | 1.0 | 2.0 |
age = pd.Series([30, 20, 50], index=['alice', 'bob', 'julie'])
age
alice 30 bob 20 julie 50 dtype: int64
# Ecrire un DataFrame dans un fichier CSV
print(df, '\n')
df.to_csv('my_data.csv') # ça écrit dans un fichier CSV
!cat my_data.csv # on affiche le fichier CSV (! permet de passer une commande de l'OS)
prenom taille sexe age 30.0 alice NaN NaN NaN bill 170.0 f 20.0 bob 175.0 h NaN eve 180.0 f 50.0 julie NaN NaN NaN liz 160.0 b age,prenom,taille,sexe 30.0,alice,, ,bill,170.0,f 20.0,bob,175.0,h ,eve,180.0,f 50.0,julie,, ,liz,160.0,b
# Ecrire un DataFrame dans un fichier JSON
print(df3, '\n')
df3.to_json('my_data.json')
!cat my_data.json
x y z a 2.0 1.0 2.0 b 1.0 1.0 -1.0 c 3.0 -1.0 4.0 {"x":{"a":2.0,"b":1.0,"c":3.0},"y":{"a":1.0,"b":1.0,"c":-1.0},"z":{"a":2.0,"b":-1.0,"c":4.0}}
# Lire un fichier CSV pour remplir un DataFrame
new_df = pd.read_csv('my_data.csv')
print(new_df)
age prenom taille sexe 0 30.0 alice NaN NaN 1 NaN bill 170.0 f 2 20.0 bob 175.0 h 3 NaN eve 180.0 f 4 50.0 julie NaN NaN 5 NaN liz 160.0 b
# Lire un fichier JSON pour remplir un DataFrame
new_df3 = pd.read_json('my_data.json')
print(new_df3)
x y z a 2 1 2 b 1 1 -1 c 3 -1 4
# Importer avec seaborn
import seaborn as sns
titanic = sns.load_dataset('titanic')
titanic.head()
survived | pclass | sex | age | sibsp | parch | fare | embarked | class | who | adult_male | deck | embark_town | alive | alone | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0 | 3 | male | 22.0 | 1 | 0 | 7.2500 | S | Third | man | True | NaN | Southampton | no | False |
1 | 1 | 1 | female | 38.0 | 1 | 0 | 71.2833 | C | First | woman | False | C | Cherbourg | yes | False |
2 | 1 | 3 | female | 26.0 | 0 | 0 | 7.9250 | S | Third | woman | False | NaN | Southampton | yes | True |
3 | 1 | 1 | female | 35.0 | 1 | 0 | 53.1000 | S | First | woman | False | C | Southampton | yes | False |
4 | 0 | 3 | male | 35.0 | 0 | 0 | 8.0500 | S | Third | man | True | NaN | Southampton | no | True |