Skip to content

pandas: Ottenere/impostare valori di elementi con at, iat, loc, iloc

Python

Usa at, iat, loc o qualsiasi iloc per accedere ai dati in posizione in pandas.DataFrame e ottenere/impostare valori. Scrivi at[], non at().

Le differenze sono le seguenti:

  • Vieni a specificare la posizione
    • at, loc : Etichetta riga/colonna (nome)
    • iat, iloc : numero di riga/colonna (posizione intera)
  • Dati che puoi ottenere/impostare
    • at, iat : valore singolo
    • loc, iloc : valori singoli o multipli

In questo articolo vengono descritti i seguenti contenuti.

  • at, iat : accedi e ottieni/imposta un singolo valore
  • loc, iloc : consenti di accedere e ottenere/impostare valori singoli o multipli
    • Accedi a un unico valore
    • Accedi a più valori
    • Accedi a righe e colonne
    • Maschera di matrice booleana e pandas.Serie
  • Etichette di riga/colonna duplicato
  • Specificare per numero ed etichetta
  • Conversione di tipo implicita quando si seleziona una riga come pandas.Series

Puoi anche selezionare righe e colonne di pandas.DataFrame ed elementi di pandas.Series indicizzando [].

Si noti che get_value() e ix[] precedentemente fornito sono stati rimossi nella versione 1.0.

Utilizza il seguente file CSV nel codice di esempio.

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 : accedi e ottieni/imposta un singolo valore

È possibile specificare la posizione in base all’etichetta di riga/colonna (nome) in at. Oltre a ottenere i dati, puoi anche impostare (assegnare) un nuovo valore.

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

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

È possibile specificare la posizione in base al numero di riga/colonna (indicizzazione basata su 0) in iat.

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

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

loc, iloc : consenti di accedere e ottenere/impostare valori singoli o multipli

loc e iloc possono accedere non solo a un singolo valore, ma anche a più valori.

È possibile specificare la posizione per etichetta di riga/colonna per loc e per numero di riga/colonna per iloc.

Accedi a un unico valore

È possibile accedere a un unico valore con loc e iloc oltre che con at e iat. Tuttavia, at e iat sono più veloci di loc e 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

Accedi a più valori

Per accedere a più valori, specifica un gruppo di dati con un elenco [a, b, c, …] e slice start:stop:step. pandas.Series o pandas.DataFrame viene restituito.

Vedere l’articolo seguente per l’utilizzo di base delle sezioni. Puoi omettere il passaggio.

Si noti che quando si specifica con la fetta start:stop:step, il valore di stop è incluso in loc (etichetta riga/colonna). Il valore di stop non è incluso in iloc (numero riga/colonna) come sezioni normali.

Quando da un elenco, le righe e le colonne sono disposte nell’ordine dell’elenco specificato.

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'>

Ad esempio, puoi estrarre righe pari/dispari specificando il passaggio.

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'>

È possibile aggiungere più valori contemporaneamente.

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

Accedi a righe e colonne

È possibile selezionare righe e colonne con df[]. Righe e colonne sono specificate come segue.

  • Righe: fetta di etichetta/numero di riga
  • Colonne: etichetta di colonna o elenco di etichette di colonna
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

Puoi specificare righe e colonne in vari modi con loc e iloc.

Se ometti di specificare le colonne con loc o iloc, le righe vengono selezionate. È possibile specificare per etichetta/numero di riga o un elenco degli stessi.

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'>

Puoi selezionare le colonne con loc e iloc specificando le righe come :. È possibile specificare per fetta.

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'>

Quando si seleziona una singola riga o colonna, pandas.Series viene restituito quando specificato da un valore scalare e pandas.DataFrame viene restituito quando specificato da una sezione o da un elenco.

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'>

Si noti che la selezione di una riga come pandas.Series può comportare una conversione di tipo implicita. Vedi sotto per i dettagli.

Maschera di matrice booleana e pandas.Serie

Puoi mascherare i dati con un array booleano (list, numpy.ndarray, ecc.). Nell’esempio, l’array booleano è specificato in righe, ma può anche essere specificato in colonne.

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

Se il numero di elementi non corrisponde, viene generato un errore.

l_bool_wrong = [True, False, False]

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

Puoi anche specificare un pandas.Series booleano in loc. I dati vengono mascherati in base all’etichetta, non all’ordine.

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

Non è possibile specificare pandas.Serie in 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

Anche in loc, viene generato un errore se le etichette non continue.

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

Etichette di riga/colonna duplicato

Le colonne dell’indice delle etichette di riga e delle etichette di colonna possono contenere valori duplicati.

Prendi pandas.DataFrame con etichette di righe e colonne duplicate come esempio.

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

Per at e loc, la specifica di etichette duplicate seleziona gli elementi corrispondenti moltiplicati.

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'>

Quando si specifica per numero di riga/colonna con iat e iloc, non importa se le etichette sono duplicate.

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

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

Se non ci sono ragioni valide, è meglio utilizzare valori univoci per i nomi di riga e colonna.

Puoi controllare se le etichette di riga e colonna sono univoche (non duplicate) con index.is_unique e columns.is_unique.

print(df_duplicated.index.is_unique)
# False

print(df_duplicated.columns.is_unique)
# False

Vedere l’articolo seguente su come rinominare le etichette di riga e colonna.

Specificare per numero ed etichetta

Se si desidera specificare la posizione in base al numero e all’etichetta, è possibile utilizzare at o loc e index o gli attributi di colonna.

È possibile ottenere le etichette di riga/colonna dal numero di riga/colonna con gli attributi di indice e colonna.

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

È possibile specificare sezioni ed elenchi.

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

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

Usando this e at o loc, puoi specificare la posizione per numero ed etichetta.

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

È possibile scrivere [, loc o iloc] come segue, ma questo è chiamato indicizzazione concatenata ed è una causa di SettingWithCopyWarning.

Questo non è un problema se ottenere e controllare solo i dati, ma tieni presente che l’assegnazione di nuovi valori può produrre risultati imprevisti.

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

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

Conversione di tipo implicita quando si seleziona una riga come pandas.Series

Quando si seleziona una riga come pandas.Series con loc o iloc, il tipo di elemento può essere convertito in modo implicito se il tipo di dati dtype di ciascuna colonna nel pandas.DataFrame originale è diverso.

Utilizzare un pandas.DataFrame con colonne di interi int e numeri in virgola mobile 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

Se ottieni una riga come pandas.Series in loc o iloc, il suo tipo di dati è float. Gli elementi nelle colonne int vengono convertiti in 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'>

Se scrivi quanto segue, viene restituito un elemento di pandas.Series convertito in float.

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

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

Puoi ottenere elementi del tipo originale con at o iat.

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

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

Se una riga viene selezionata da un elenco o una sezione in loc o iloc, viene restituito pandas.DataFrame anziché pandas.Series. In questo caso, viene mantenuto il tipo di dati originale.

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