
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
