
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