Obtener el valor de la primera fila de una columna determinada

Resuelto Ahmed Haque asked hace 10 años • 10 respuestas

Esta parece una pregunta ridículamente fácil... pero no veo la respuesta fácil que esperaba.

Entonces, ¿cómo obtengo el valor en una enésima fila de una columna determinada en Pandas? (Estoy particularmente interesado en la primera fila, pero también me interesaría una práctica más general).

Por ejemplo, digamos que quiero introducir el valor 1,2 Btimecomo variable.

¿Cuál es la forma correcta de hacer esto?

>>> 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
Ahmed Haque avatar Aug 12 '14 06:08 Ahmed Haque
Aceptado

Para seleccionar la ithfila, utiliceiloc :

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

Para seleccionar el iésimo valor en la Btimecolumna, puede usar:

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

Hay una diferencia entre df_test['Btime'].iloc[0](recomendado) y df_test.iloc[0]['Btime']:

Los DataFrames almacenan datos en bloques basados ​​en columnas (donde cada bloque tiene un único tipo). Si selecciona primero por columna, se puede devolver una vista (que es más rápido que devolver una copia) y se conserva el tipo de letra original. Por el contrario, si selecciona primero por fila y si el DataFrame tiene columnas de diferentes tipos, Pandas copia los datos en una nueva serie de tipo de objeto. Entonces, seleccionar columnas es un poco más rápido que seleccionar filas. Así, aunque df_test.iloc[0]['Btime']funciona, df_test['Btime'].iloc[0]es un poquito más eficiente.

Hay una gran diferencia entre los dos cuando se trata de asignación. df_test['Btime'].iloc[0] = xafecta df_test, pero df_test.iloc[0]['Btime'] puede que no. Consulte a continuación una explicación del por qué. Debido a que una diferencia sutil en el orden de indexación genera una gran diferencia en el comportamiento, es mejor utilizar una asignación de indexación única:

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

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

La forma recomendada de asignar nuevos valores a un DataFrame es evitar la indexación encadenada y, en su lugar, utilizar el método mostrado por Andrew .

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

o

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

El último método es un poco más rápido, porque df.loctiene que convertir las etiquetas de filas y columnas en índices posicionales, por lo que se necesita un poco menos de conversión si lo usa df.ilocen su lugar.


df['Btime'].iloc[0] = xFunciona, pero no se recomienda:

Aunque esto funciona, aprovecha la forma en que se implementan actualmente los DataFrames . No hay garantía de que Pandas tenga que funcionar de esta manera en el futuro. En particular, aprovecha el hecho de que (actualmente) df['Btime']siempre devuelve una vista (no una copia), por lo que df['Btime'].iloc[n] = xpuede usarse para asignar un nuevo valor en la enésima ubicación de la Btimecolumna de df.

Dado que Pandas no ofrece garantías explícitas sobre cuándo los indexadores devuelven una vista versus una copia, las asignaciones que utilizan indexación encadenada generalmente siempre generan un SettingWithCopyWarningaunque en este caso la asignación logra modificar 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'] = xNo funciona:

Por el contrario, la asignación con df.iloc[0]['bar'] = 123no funciona porque df.iloc[0]devuelve 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

Advertencia : ya lo había sugerido anteriormente df_test.ix[i, 'Btime']. Pero no se garantiza que esto le proporcione el ithvalor, ya que ixintenta indexar por etiqueta antes de intentar indexar por posición . Entonces, si el DataFrame tiene un índice entero que no está ordenado comenzando en 0, entonces el uso ix[i]devolverá la fila etiquetada i en lugar de la ithfila. Por ejemplo,

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'
unutbu avatar Aug 11 '2014 23:08 unutbu

Otra forma de hacer esto:

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

Esta forma parece ser más rápida que usar .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)
Abdulrahman Bres avatar Feb 28 '2018 17:02 Abdulrahman Bres