Skip to content

pandas : Obtenir/définir les valeurs des éléments avec at, iat, loc, iloc

Utilisez at, iat, loc ou iloc pour accéder aux données à n’importe quel emplacement dans pandas.DataFrame et obtenir/définir des valeurs. Écrivez à[], pas à().

Les différences sont les suivantes :

  • Comment spécifier le poste
    • at, loc : étiquette de ligne/colonne (nom)
    • iat, iloc : Numéro de ligne/colonne (position entière)
  • Données que vous pouvez obtenir/définir
    • at, iat : Valeur unique
    • loc, iloc : Valeurs uniques ou multiples

Cet article décrit le contenu suivant.

  • at, iat : Accéder et obtenir/définir une valeur unique
  • loc, iloc : Accéder et obtenir/définir des valeurs uniques ou multiples
    • Accéder à une seule valeur
    • Accéder à plusieurs valeurs
    • Accéder aux lignes et aux colonnes
    • Masque par tableau booléen et pandas.Series
  • Libellés de ligne/colonne dupliqués
  • Spécifier par numéro et étiquette
  • Conversion de type implicite lors de la sélection d’une ligne en tant que pandas.Series

Vous pouvez également sélectionner des lignes et des colonnes de pandas.DataFrame et des éléments de pandas.Series en indexant [].

Notez que get_value() et ix[] fournis précédemment ont été supprimés dans la version 1.0.

Utilisez le fichier CSV suivant dans l’exemple de code.

import pandas as pd

print(pd.__version__)
# 1.4.1

df = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=0)
print(df)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       42    CA     92
# Charlie   18    CA     70
# Dave      68    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

at, iat : Accéder et obtenir/définir une valeur unique

Vous pouvez spécifier la position par étiquette de ligne/colonne (nom) dans at. En plus d’obtenir des données, vous pouvez également définir (attribuer) une nouvelle valeur.

print(df.at['Bob', 'age'])
# 42

df.at['Bob', 'age'] = 60
print(df.at['Bob', 'age'])
# 60

Vous pouvez spécifier la position par numéro de ligne/colonne (indexation basée sur 0) dans iat.

print(df.iat[1, 0])
# 60

df.iat[1, 0] = 42
print(df.iat[1, 0])
# 42

loc, iloc : Accéder et obtenir/définir des valeurs uniques ou multiples

loc et iloc peuvent accéder non seulement à une seule valeur, mais également à plusieurs valeurs.

Vous pouvez spécifier la position par étiquette de ligne/colonne pour loc et par numéro de ligne/colonne pour iloc.

Accéder à une seule valeur

Vous pouvez accéder à une seule valeur avec loc et iloc ainsi qu’avec at et iat. Cependant, at et iat sont plus rapides que loc et iloc.

print(df.loc['Bob', 'age'])
# 42

print(df.iloc[1, 0])
# 42
df.loc['Bob', 'age'] = 60
print(df.loc['Bob', 'age'])
# 60

df.iloc[1, 0] = 42
print(df.iloc[1, 0])
# 42

Accéder à plusieurs valeurs

Pour accéder à plusieurs valeurs, spécifiez un groupe de données avec une liste [a, b, c, …] et une tranche start:stop:step. pandas.Series ou pandas.DataFrame est renvoyé.

Consultez l’article suivant pour l’utilisation de base des tranches. Vous pouvez omettre l’étape.

Notez que lors de la spécification avec la tranche start:stop:step, la valeur de stop est incluse dans loc (étiquette de ligne/colonne). La valeur de stop n’est pas incluse dans iloc (numéro de ligne/colonne) en tant que tranches normales.

Lorsqu’elles sont spécifiées par une liste, les lignes et les colonnes sont organisées dans l’ordre de la liste spécifiée.

print(df.loc['Bob':'Dave', 'age'])
print(type(df.loc['Bob':'Dave', 'age']))
# name
# Bob        42
# Charlie    18
# Dave       68
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(df.loc[:'Dave', ['point', 'age']])
print(type(df.loc[:'Dave', ['point', 'age']]))
#          point  age
# name               
# Alice       64   24
# Bob         92   42
# Charlie     70   18
# Dave        70   68
# <class 'pandas.core.frame.DataFrame'>

print(df.iloc[:3, [2, 0]])
print(type(df.iloc[:3, [2, 0]]))
#          point  age
# name               
# Alice       64   24
# Bob         92   42
# Charlie     70   18
# <class 'pandas.core.frame.DataFrame'>

Par exemple, vous pouvez extraire des lignes paires/impaires en spécifiant step.

print(df.iloc[::2, 0])
print(type(df.iloc[::2, 0]))
# name
# Alice      24
# Charlie    18
# Ellen      24
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

print(df.iloc[1::2, 0])
print(type(df.iloc[1::2, 0]))
# name
# Bob      42
# Dave     68
# Frank    30
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>

Vous pouvez attribuer plusieurs valeurs à la fois.

df.loc['Bob':'Dave', 'age'] = 0
print(df.loc['Bob':'Dave', 'age'])
# name
# Bob        0
# Charlie    0
# Dave       0
# Name: age, dtype: int64

df.loc['Bob':'Dave', 'age'] = [20, 30, 40]
print(df.loc['Bob':'Dave', 'age'])
# name
# Bob        20
# Charlie    30
# Dave       40
# Name: age, dtype: int64

Accéder aux lignes et aux colonnes

Vous pouvez sélectionner des lignes et des colonnes avec df[]. Les lignes et les colonnes sont spécifiées comme suit.

  • Lignes : tranche d’étiquette/numéro de ligne
  • Colonnes : étiquette de colonne ou liste d’étiquettes de colonne
print(df['Bob':'Ellen'])
#          age state  point
# name                     
# Bob       20    CA     92
# Charlie   30    CA     70
# Dave      40    TX     70
# Ellen     24    CA     88

print(df[:3])
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       20    CA     92
# Charlie   30    CA     70

print(df['age'])
# name
# Alice      24
# Bob        20
# Charlie    30
# Dave       40
# Ellen      24
# Frank      30
# Name: age, dtype: int64

print(df[['age', 'point']])
#          age  point
# name               
# Alice     24     64
# Bob       20     92
# Charlie   30     70
# Dave      40     70
# Ellen     24     88
# Frank     30     57

Vous pouvez spécifier des lignes et des colonnes de différentes manières avec loc et iloc.

Si vous omettez de spécifier des colonnes avec loc ou iloc, les lignes sont sélectionnées. Il est possible de spécifier par étiquette/numéro de ligne ou une liste de ceux-ci.

print(df.loc['Bob'])
print(type(df.loc['Bob']))
# age      20
# state    CA
# point    92
# Name: Bob, dtype: object
# <class 'pandas.core.series.Series'>

print(df.iloc[[4, 1]])
print(type(df.iloc[[4, 1]]))
#        age state  point
# name                   
# Ellen   24    CA     88
# Bob     20    CA     92
# <class 'pandas.core.frame.DataFrame'>

Vous pouvez sélectionner des colonnes avec loc et iloc en spécifiant les lignes comme :. Il est possible de spécifier par tranche.

print(df.loc[:, 'age':'point'])
print(type(df.loc[:, 'age':'point']))
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       20    CA     92
# Charlie   30    CA     70
# Dave      40    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57
# <class 'pandas.core.frame.DataFrame'>

print(df.iloc[:, [0, 2]])
print(type(df.iloc[:, [0, 2]]))
#          age  point
# name               
# Alice     24     64
# Bob       20     92
# Charlie   30     70
# Dave      40     70
# Ellen     24     88
# Frank     30     57
# <class 'pandas.core.frame.DataFrame'>

Lors de la sélection d’une seule ligne ou colonne, pandas.Series est renvoyé lorsqu’il est spécifié par une valeur scalaire, et pandas.DataFrame est renvoyé lorsqu’il est spécifié par une tranche ou une liste.

print(df.loc['Bob'])
print(type(df.loc['Bob']))
# age      20
# state    CA
# point    92
# Name: Bob, dtype: object
# <class 'pandas.core.series.Series'>

print(df.loc['Bob':'Bob'])
print(type(df.loc['Bob':'Bob']))
#       age state  point
# name                  
# Bob    20    CA     92
# <class 'pandas.core.frame.DataFrame'>

print(df.loc[['Bob']])
print(type(df.loc[['Bob']]))
#       age state  point
# name                  
# Bob    20    CA     92
# <class 'pandas.core.frame.DataFrame'>
print(df.iloc[:, 1])
print(type(df.iloc[:, 1]))
# name
# Alice      NY
# Bob        CA
# Charlie    CA
# Dave       TX
# Ellen      CA
# Frank      NY
# Name: state, dtype: object
# <class 'pandas.core.series.Series'>

print(df.iloc[:, 1:2])
print(type(df.iloc[:, 1:2]))
#         state
# name         
# Alice      NY
# Bob        CA
# Charlie    CA
# Dave       TX
# Ellen      CA
# Frank      NY
# <class 'pandas.core.frame.DataFrame'>

print(df.iloc[:, [1]])
print(type(df.iloc[:, [1]]))
#         state
# name         
# Alice      NY
# Bob        CA
# Charlie    CA
# Dave       TX
# Ellen      CA
# Frank      NY
# <class 'pandas.core.frame.DataFrame'>

Notez que la sélection d’une ligne en tant que pandas.Series peut entraîner une conversion de type implicite. Voir ci-dessous pour plus de détails.

Masque par tableau booléen et pandas.Series

Vous pouvez masquer les données avec un tableau booléen (list, numpy.ndarray, etc.). Dans l’exemple, le tableau booléen est spécifié pour les lignes, mais il peut également être spécifié pour les colonnes.

l_bool = [True, False, False, True, False, True]

print(df.loc[l_bool, ['age', 'point']])
#        age  point
# name             
# Alice   24     64
# Dave    40     70
# Frank   30     57

print(df.iloc[l_bool, [0, 2]])
#        age  point
# name             
# Alice   24     64
# Dave    40     70
# Frank   30     57

Si le nombre d’éléments ne correspond pas, une erreur est générée.

l_bool_wrong = [True, False, False]

# print(df.loc[l_bool_wrong, ['age', 'point']])
# IndexError: Boolean index has wrong length: 3 instead of 6

Vous pouvez également spécifier un booléen pandas.Series dans loc. Les données sont masquées en fonction de l’étiquette et non de la commande.

s_bool = pd.Series([True, False, True, True, False, False],
                   index=reversed(df.index))
print(s_bool)
# Frank       True
# Ellen      False
# Dave        True
# Charlie     True
# Bob        False
# Alice      False
# dtype: bool

print(df.loc[s_bool, ['age', 'point']])
#          age  point
# name               
# Charlie   30     70
# Dave      40     70
# Frank     30     57

Vous ne pouvez pas spécifier pandas.Series dans iloc.

# print(df.iloc[s_bool, [0, 2]])
# ValueError: Location based indexing can only have [integer,
# integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types

Même en loc, une erreur est levée si les étiquettes ne correspondent pas.

s_bool_wrong = pd.Series([True, False, False], index=['Frank', 'Ellen', 'Dave'])
print(s_bool_wrong)
# Frank     True
# Ellen    False
# Dave     False
# dtype: bool

# print(df.loc[s_bool_wrong, ['age', 'point']])
# IndexingError: Unalignable boolean Series provided as indexer
# (index of the boolean Series and of the indexed object do not match).

s_bool_wrong2 = pd.Series([True, False, False, True, False, True],
                          index=['A', 'B', 'C', 'D', 'E', 'F'])
print(s_bool_wrong2)
# A     True
# B    False
# C    False
# D     True
# E    False
# F     True
# dtype: bool

# print(df.loc[s_bool_wrong2, ['age', 'point']])
# IndexingError: Unalignable boolean Series provided as indexer
# (index of the boolean Series and of the indexed object do not match).

Libellés de ligne/colonne dupliqués

L’index des libellés de ligne et les colonnes des libellés de colonne peuvent contenir des valeurs en double.

Prenez pandas.DataFrame avec des étiquettes de ligne et de colonne en double comme exemple.

df_duplicated = pd.read_csv('data/src/sample_pandas_normal.csv', index_col=2)
df_duplicated.columns = ['name', 'age', 'age']
print(df_duplicated)
#           name  age  age
# state                   
# NY       Alice   24   64
# CA         Bob   42   92
# CA     Charlie   18   70
# TX        Dave   68   70
# CA       Ellen   24   88
# NY       Frank   30   57

Pour at et loc, la spécification d’étiquettes en double sélectionne les éléments multiples correspondants.

print(df_duplicated.at['NY', 'age'])
print(type(df_duplicated.at['NY', 'age']))
#        age  age
# state          
# NY      24   64
# NY      30   57
# <class 'pandas.core.frame.DataFrame'>

print(df_duplicated.loc['NY', 'age'])
print(type(df_duplicated.loc['NY', 'age']))
#        age  age
# state          
# NY      24   64
# NY      30   57
# <class 'pandas.core.frame.DataFrame'>

Lors de la spécification par numéro de ligne/colonne avec iat et iloc, peu importe si les étiquettes sont dupliquées.

print(df_duplicated.iat[0, 1])
# 24

print(df_duplicated.iloc[:2, [0, 1]])
#         name  age
# state            
# NY     Alice   24
# CA       Bob   42

S’il n’y a pas de raison valable, il est préférable d’utiliser des valeurs uniques pour les noms de ligne et de colonne.

Vous pouvez vérifier si les étiquettes de ligne et de colonne sont uniques (non dupliquées) avec index.is_unique et columns.is_unique.

print(df_duplicated.index.is_unique)
# False

print(df_duplicated.columns.is_unique)
# False

Consultez l’article suivant pour savoir comment renommer les étiquettes de ligne et de colonne.

Spécifier par numéro et étiquette

Si vous souhaitez spécifier la position par numéro et étiquette, vous pouvez utiliser les attributs at ou loc et index ou column.

Vous pouvez obtenir ses étiquettes de ligne/colonne à partir du numéro de ligne/colonne avec les attributs d’index et de colonne.

print(df)
#          age state  point
# name                     
# Alice     24    NY     64
# Bob       20    CA     92
# Charlie   30    CA     70
# Dave      40    TX     70
# Ellen     24    CA     88
# Frank     30    NY     57

print(df.index[2])
# Charlie

print(df.columns[1])
# state

Vous pouvez spécifier des tranches et des listes.

print(df.index[2:4])
# Index(['Charlie', 'Dave'], dtype="object", name="name")

print(df.columns[[0, 2]])
# Index(['age', 'point'], dtype="object")

En utilisant this et at ou loc, vous pouvez spécifier l’emplacement par numéro et étiquette.

print(df.at[df.index[2], 'age'])
# 30

print(df.loc[['Alice', 'Dave'], df.columns[[0, 2]]])
#        age  point
# name             
# Alice   24     64
# Dave    40     70

Il est possible d’écrire [], loc ou iloc à plusieurs reprises comme suit, mais cela s’appelle l’indexation chaînée et est une cause de SettingWithCopyWarning.

Ce n’est pas un problème si vous obtenez et vérifiez uniquement des données, mais sachez que l’attribution de nouvelles valeurs peut produire des résultats inattendus.

print(df['age'][2])
# 30

print(df.loc[['Alice', 'Dave']].iloc[:, [0, 2]])
#        age  point
# name             
# Alice   24     64
# Dave    40     70

Conversion de type implicite lors de la sélection d’une ligne en tant que pandas.Series

Lors de la sélection d’une ligne en tant que pandas.Series avec loc ou iloc, le type d’élément peut être implicitement converti si le type de données dtype de chaque colonne dans le pandas.DataFrame d’origine est différent.

Utilisez un pandas.DataFrame avec des colonnes d’entiers int et des nombres à virgule flottante float.

df_mix = pd.DataFrame({'col_int': [0, 1, 2], 'col_float': [0.1, 0.2, 0.3]}, index=['A', 'B', 'C'])
print(df_mix)
#    col_int  col_float
# A        0        0.1
# B        1        0.2
# C        2        0.3

print(df_mix.dtypes)
# col_int        int64
# col_float    float64
# dtype: object

Si vous obtenez une ligne en tant que pandas.Series dans loc ou iloc, son type de données est float. Les éléments dans les colonnes int sont convertis en float.

print(df_mix.loc['B'])
# col_int      1.0
# col_float    0.2
# Name: B, dtype: float64

print(type(df_mix.loc['B']))
# <class 'pandas.core.series.Series'>

Si vous écrivez ce qui suit, un élément de pandas.Series converti en float est renvoyé.

print(df_mix.loc['B']['col_int'])
# 1.0

print(type(df_mix.loc['B']['col_int']))
# <class 'numpy.float64'>

Vous pouvez obtenir des éléments du type d’origine avec at ou iat.

print(df_mix.at['B', 'col_int'])
# 1

print(type(df_mix.at['B', 'col_int']))
# <class 'numpy.int64'>

Si une ligne est sélectionnée par une liste ou une tranche dans loc ou iloc, pandas.DataFrame est renvoyé au lieu de pandas.Series. Dans ce cas, le type de données d’origine est conservé.

print(df_mix.loc[['B']])
#    col_int  col_float
# B        1        0.2

print(type(df_mix.loc[['B']]))
# <class 'pandas.core.frame.DataFrame'>

print(df_mix.loc[['B']].dtypes)
# col_int        int64
# col_float    float64
# dtype: object