Panda: ottieni il valore della prima riga di una determinata colonna


300

Sembra una domanda ridicolmente facile ... ma non vedo la risposta facile che mi aspettavo.

Quindi, come posso ottenere il valore in un'ennesima riga di una determinata colonna in Panda? (Sono particolarmente interessato alla prima fila, ma sarei interessato anche a una pratica più generale).

Ad esempio, supponiamo di voler estrarre il valore 1.2 in Btime come variabile.

Qual è il modo giusto per farlo?

df_test =

  ATime   X   Y   Z   Btime  C   D   E
0    1.2  2  15   2    1.2  12  25  12
1    1.4  3  12   1    1.3  13  22  11
2    1.5  1  10   6    1.4  11  20  16
3    1.6  2   9  10    1.7  12  29  12
4    1.9  1   1   9    1.9  11  21  19
5    2.0  0   0   0    2.0   8  10  11
6    2.4  0   0   0    2.4  10  12  15

7
Se volevi semplicemente che la prima riga df_test.head(1)funzionasse, il modulo più generale è quello di utilizzare iloccome risposta da unutbu
EdChum

1
Vuoi solo il valore 1.2? o la serie di lunghezza 1 che ottieni df_test.head(1), che conterrà anche l'indice? Per ottenere solo il valore do df_test.head(1).item(), o tolist()quindi tagliare.
smci,

Risposte:


472

Per selezionare la ithriga, utilizzareiloc :

In [31]: df_test.iloc[0]
Out[31]: 
ATime     1.2
X         2.0
Y        15.0
Z         2.0
Btime     1.2
C        12.0
D        25.0
E        12.0
Name: 0, dtype: float64

Per selezionare il valore ith nella Btimecolonna è possibile utilizzare:

In [30]: df_test['Btime'].iloc[0]
Out[30]: 1.2

C'è una differenza tra df_test['Btime'].iloc[0](consigliato) e df_test.iloc[0]['Btime']:

DataFrames memorizza i dati in blocchi basati su colonne (dove ogni blocco ha un solo tipo). Se si seleziona prima per colonna, è possibile restituire una vista (che è più veloce della restituzione di una copia) e il tipo originale viene conservato. Al contrario, se si seleziona prima per riga e se DataFrame ha colonne di tipi diversi, Pandas copia i dati in una nuova serie di tipi tipo. Quindi la selezione delle colonne è un po 'più veloce della selezione delle righe. Pertanto, sebbene df_test.iloc[0]['Btime']funzioni, df_test['Btime'].iloc[0]è un po 'più efficiente.

C'è una grande differenza tra i due quando si tratta di assegnazione. df_test['Btime'].iloc[0] = xcolpisce df_test, ma df_test.iloc[0]['Btime'] potrebbe non farlo. Vedi sotto per una spiegazione del perché. Poiché una sottile differenza nell'ordine di indicizzazione fa una grande differenza nel comportamento, è meglio usare una singola assegnazione di indicizzazione:

df.iloc[0, df.columns.get_loc('Btime')] = x

df.iloc[0, df.columns.get_loc('Btime')] = x (consigliato):

Il modo consigliato per assegnare nuovi valori a un DataFrame è evitare l'indicizzazione concatenata e utilizzare invece il metodo mostrato da andrew ,

df.loc[df.index[n], 'Btime'] = x

o

df.iloc[n, df.columns.get_loc('Btime')] = x

Quest'ultimo metodo è un po 'più veloce, perché df.locdeve convertire le etichette di riga e colonna in indici posizionali, quindi è necessaria una conversione un po' meno se si utilizza df.ilocinvece.


df['Btime'].iloc[0] = x funziona, ma non è raccomandato:

Sebbene funzioni, sta sfruttando il modo in cui i DataFrames sono attualmente implementati. Non vi è alcuna garanzia che i panda debbano lavorare in questo modo in futuro. In particolare, sta sfruttando il fatto che (attualmente) df['Btime']restituisce sempre una vista (non una copia), quindi df['Btime'].iloc[n] = xpuò essere utilizzato per assegnare un nuovo valore all'ennesima posizione della Btimecolonna di df.

Poiché Pandas non fornisce garanzie esplicite su quando gli indicizzatori restituiscono una vista rispetto a una copia, le assegnazioni che utilizzano l'indicizzazione concatenata generano sempre un valore SettingWithCopyWarninganche se in questo caso l'assegnazione riesce a modificare df:

In [22]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [24]: df['bar'] = 100
In [25]: df['bar'].iloc[0] = 99
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

In [26]: df
Out[26]: 
  foo  bar
0   A   99  <-- assignment succeeded
2   B  100
1   C  100

df.iloc[0]['Btime'] = x non funziona:

Al contrario, l'assegnazione con df.iloc[0]['bar'] = 123non funziona perché df.iloc[0]restituisce una copia:

In [66]: df.iloc[0]['bar'] = 123
/home/unutbu/data/binky/bin/ipython:1: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

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

In [67]: df
Out[67]: 
  foo  bar
0   A   99  <-- assignment failed
2   B  100
1   C  100

Attenzione : avevo precedentemente suggerito df_test.ix[i, 'Btime']. Ma questo non è garantito per darti il ithvalore poiché ixcerca di indicizzare per etichetta prima di provare a indicizzare per posizione . Quindi, se DataFrame ha un indice intero che non è in ordine ordinato a partire da 0, allora l'utilizzo ix[i]restituirà la riga etichettata i anziché la ithriga. Per esempio,

In [1]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])

In [2]: df
Out[2]: 
  foo
0   A
2   B
1   C

In [4]: df.ix[1, 'foo']
Out[4]: 'C'

1
@CristianCiupitu: DataFrames memorizza i dati in blocchi basati su colonne (in cui ogni blocco ha un singolo tipo). Se si seleziona prima per colonna, è possibile restituire una vista (che è più veloce della restituzione di una copia) e il tipo originale viene conservato. Al contrario, se si seleziona prima per riga e se DataFrame ha colonne di tipi diversi, Pandas copia i dati in una nuova serie di tipi tipo. Quindi selezionare le colonne è un po 'più veloce della selezione delle righe. Pertanto, sebbene df_test.iloc[0]['Btime']funzioni, df_test.iloc['Btime'][0]è un po 'più efficiente.
unutbu,

@unutbu, è df['Btime'].iloc[0]preferito df['Btime'].values[0]? posso vedere dalla documentazione che dice "Avviso: si consiglia di utilizzare Series.array o Series.to_numpy (), a seconda che sia necessario un riferimento ai dati sottostanti o un array NumPy". ma non sono sicuro di cosa significhi esattamente
aydow il

28

Nota che la risposta di @unutbu sarà corretta fino a quando non vuoi impostare il valore su qualcosa di nuovo, quindi non funzionerà se il tuo frame di dati è una vista.

In [4]: df = pd.DataFrame({'foo':list('ABC')}, index=[0,2,1])
In [5]: df['bar'] = 100
In [6]: df['bar'].iloc[0] = 99
/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/pandas-0.16.0_19_g8d2818e-py2.7-macosx-10.9-x86_64.egg/pandas/core/indexing.py:118: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame

See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy
  self._setitem_with_indexer(indexer, value)

Un altro approccio che funzionerà in modo coerente sia con l'impostazione che con l'ottenimento è:

In [7]: df.loc[df.index[0], 'foo']
Out[7]: 'A'
In [8]: df.loc[df.index[0], 'bar'] = 99
In [9]: df
Out[9]:
  foo  bar
0   A   99
2   B  100
1   C  100

1
Sto eseguendo il ciclo tra un mucchio di file .csv e leggendo il primo valore di una determinata colonna in ciascuno. Per qualche motivo che non posso spiegare invece di restituire il valore, a volte restituisce l'indice insieme al valore che incasina l'elaborazione. Ho fatto ricorso a df.col.unique () [0].
passero

15

Un altro modo per farlo:

first_value = df['Btime'].values[0]

In questo modo sembra essere più veloce dell'uso .iloc:

In [1]: %timeit -n 1000 df['Btime'].values[20]
5.82 µs ± 142 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [2]: %timeit -n 1000 df['Btime'].iloc[20]
29.2 µs ± 1.28 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

12
  1. df.iloc[0].head(1) - Primo set di dati solo dall'intera prima riga.
  2. df.iloc[0] - Intera prima riga nella colonna.

8

In generale, se si desidera raccogliere le prime N righe dalla colonna J dal pandas dataframemodo migliore per farlo è:

data = dataframe[0:N][:,J]

2
@anis: A questo scopo, sarebbe stato meglio scrivere una nuova domanda chiedendo la soluzione più generale e rispondendo da soli, credo.
jonathan.scholbach,

3

Per ottenere ad esempio il valore dalla colonna 'test' e dalla riga 1 funziona come

df[['test']].values[0][0]

poiché df[['test']].values[0]restituisce solo un array


1

Un altro modo per ottenere la prima riga e preservare l'indice:

x = df.first('d') # Returns the first day. '3d' gives first three days.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.