Skip to article frontmatterSkip to article content
import pandas as pd
import numpy as np # pandas reposant sur numpy on a souvent besoin des deux librairies

introduction


copier une dataframe ou une série

# le code
df = pd.read_csv('data/titanic.csv', index_col='PassengerId')
df2 = df.copy()
df2.loc[552, 'Age'] = 100
df2.head(1)
Loading...
df.head(1)
Loading...

créer une nouvelle colonne

# le code
df['Deceased'] = 1 - df['Survived']
df.head(3)
Loading...

rappels python, numpy

# le code - rappels sur Python

L = [10, 20, 30, 40, 60]
L[0] = "Hello !"
print(L)
L[1:3] = [200, 300, 500]
L
['Hello !', 20, 30, 40, 60]
['Hello !', 200, 300, 500, 40, 60]
# le code - rappels sur numpy

mat = np.arange(12).reshape((4, 3))
mat[0:2, 0:2] = 999
mat
array([[999, 999, 2], [999, 999, 5], [ 6, 7, 8], [ 9, 10, 11]])
# le code - accéder à un élément de la df 
# ATTENTION: ça marche mais IL NE FAUT PAS FAIRE COMME CA !

df['Age'][552]
np.float64(27.0)

localiser en pandas

ligne,colonne vs colonne, ligne


localisation avec loc et iloc

df = pd.read_csv('data/titanic.csv', index_col='PassengerId')
df.head(2)
Loading...
df.tail(1)
Loading...
df.loc[552, 'Name']
'Sharp, Mr. Percival James R'
df.iloc[0, 2]
'Sharp, Mr. Percival James R'
df.iloc[-1, 2]
'Richards, Master. George Sibley'

sélection multiple

df.loc[552]
Survived 0 Pclass 2 Name Sharp, Mr. Percival James R Sex male Age 27.0 SibSp 0 Parch 0 Ticket 244358 Fare 26.0 Cabin NaN Embarked S Name: 552, dtype: object
# bien sûr les index choisis
# ne pas forcément contigus
df.loc[[552, 832]]
Loading...
# choisir plusieurs lignes et plusieurs colonnes
df.loc[[552, 832], ['Name', 'Pclass']]
Loading...
# la même avec iloc
df.iloc[[0, -1], [2, 1]]
Loading...
# plusieurs colonnes : forme #1 (le plus simple)
df[['Name', 'Pclass']]
Loading...
# plusieurs colonnes : forme #2 (le plus explicite)
df.loc[:, ['Name', 'Pclass']]
Loading...

slicing pandas et bornes


slicing avec loc par index

# les ids des 5 premières lignes
df.index[:5]
Index([552, 638, 499, 261, 395], dtype='int64', name='PassengerId')
# les noms des 5 premières colonnes
df.columns[:5]
Index(['Survived', 'Pclass', 'Name', 'Sex', 'Age'], dtype='object')
# slice avec loc -> inclusif
df.loc[ 638:261, 'Pclass': 'Age'].shape # (3, 4)
(3, 4)
# le code
df.loc[ 638:261, 'Pclass': 'Age']
Loading...
# remarquons une méthode des Index
# pour obtenir l'indice d'un index
df.columns.get_loc('Pclass'), df.index.get_loc(261)
(1, 3)

slicing avec iloc par indices

# le code
df.iloc[1:7, 1:4].shape
(6, 3)

localiser des lignes et des colonnes

# le code
df.loc[552, :].shape
df.loc[552].shape
(11,)
# le code
df.loc[:, 'Survived'].shape
(891,)
# le code
df.iloc[0, :].shape
df.iloc[0].shape
(11,)
# le code
df.iloc[:, 0].shape
(891,)

exercice sélections multiples et slicing

  1. lisez le titanic et mettez les PassengerId comme index des lignes
# votre code
  1. localisez l’élément d’index 40
    a. Quel est le type de l’élément ?
    b. localisez le nom du passager d’index 40 ?
# votre code
  1. quel est le nom de la personne qui apparaît en avant-dernier dans le fichier
# votre code
  1. localisez les 3 derniers éléments de la ligne d’index 40
# votre code
  1. localisez les 4 derniers éléments de la colonne Cabin
# votre code
df['Cabin'].iloc[-4:]
PassengerId 287 NaN 326 C32 396 NaN 832 NaN Name: Cabin, dtype: object
  1. fabriquez une dataframe contenant
# votre code

indexation par un masque

rappel sur les conditions

# le code
df = pd.read_csv('data/titanic.csv', index_col='PassengerId')

df_survived = (df['Survived'] == 1)
print(   df_survived.sum()/len(df)   )

( ((df['Sex'] == 'female') & (df['Survived'] == 1) & (df['Pclass'] == 1)).sum()
  /((df['Sex'] == 'female') & (df['Pclass'] == 1)).sum()   )
0.3838383838383838
np.float64(0.9680851063829787)

sélection par masque booléen

# le code
# on fabrique une dataframe qui contient seulement les femmes
df [ df['Sex'] == 'female' ]
Loading...

df[mask] décortiqué

# le code
mask = df.Sex == 'female'
print(type(mask))   # pandas.core.series.Series
print(mask.dtype)   # dtype('bool')
print(mask.shape)
mask.head() # un masque de booléens sur la colonne des index donc la colonne PassengerId
<class 'pandas.core.series.Series'>
bool
(891,)
PassengerId 552 False 638 False 499 True 261 False 395 True Name: Sex, dtype: bool
# on indexe directement la dataframe par un masque
df[mask].head()
Loading...
# tout sur une ligne
df[df.Sex == 'female'].head()
Loading...

exercice combinaison d’expressions booléennes

  1. en une seule ligne sélectionner la sous-dataframe des passagers
    qui ne sont pas en première classe
    et dont l’age est supérieur ou égal à 70 ans
# votre code
  1. Combien trouvez-vous de passagers ?
# votre code
  1. Accédez à la valeur Name du premier de ces passagers
# votre code
  1. Faites la même expression que la question 1
    en utilisant les fonctions numpy.logical_and, numpy.logical_not
# votre code

résumé des méthodes d’indexation

# le code
df.loc[
    # dans la dimension des lignes: une liste
    [450, 3, 67],
    # dans la dimension des colonnes: une slice
    'Sex':'Cabin':2]
Loading...
# le code
df.loc[df['Age'] >= 71, ['Sex', 'Survived']]
Loading...

règles des modifications

sélections de parties de dataframe


modification d’une copie

# le code
df = pd.read_csv('data/titanic.csv', index_col='PassengerId')
df.loc[552, 'Survived']
np.int64(0)
df['Survived'][552] = 1
# possible que df['Survived'][1] soit passé à 1, par hasard
# mais votre code est faux
# et dans tous les cas vous recevez un gros warning !
df.loc[552, 'Survived']
/tmp/ipykernel_2537/3582046640.py:1: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  df['Survived'][552] = 1
/tmp/ipykernel_2537/3582046640.py:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df['Survived'][552] = 1
np.int64(1)
# ça c'est la façon propre de faire
df.loc[552, 'Survived'] = 1
df.loc[552, 'Survived']
np.int64(1)
# la preuve
df.loc[552, 'Survived'] = 0
df.loc[552, 'Survived']
np.int64(0)
# le code
print(df['Age'][889])

# le code
df.loc[889, 'Age'] = 27.5

# le code
df['Age'][889] = 27.5
nan
/tmp/ipykernel_2537/2655944779.py:8: FutureWarning: ChainedAssignmentError: behaviour will change in pandas 3.0!
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series, because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:

df["col"][row_indexer] = value

Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy

  df['Age'][889] = 27.5
/tmp/ipykernel_2537/2655944779.py:8: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
  df['Age'][889] = 27.5

faire des copies explicites

# le code
df1 = df.loc[ :, ['Survived', 'Pclass', 'Sex'] ]
df1.loc[1, 'Survived'] = 1
# le code
df2 = df[ ['Survived', 'Pclass', 'Sex'] ].copy()
print(df2.loc[1, 'Survived'])
df2.loc[1, 'Survived'] = 0
print(df2.loc[1, 'Survived'])
print(df.loc[1, 'Survived'])
0
0
0