Solución:
Para seleccionar el ith
fila, uso iloc
:
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 el Btime
columna que podría 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 solo dtype). Si selecciona por columna primero, un vista se puede devolver (que es más rápido que devolver una copia) y se conserva el tipo d original. Por el contrario, si selecciona primero por fila, y si el DataFrame tiene columnas de diferentes tipos de datos, entonces Pandas copias los datos en una nueva serie de dtype de objeto. Por lo tanto, seleccionar columnas es un poco más rápido que seleccionar filas. Así, aunque
df_test.iloc[0]['Btime']
obras, df_test['Btime'].iloc[0]
es un poco más eficiente.
Hay una gran diferencia entre los dos cuando se trata de asignación.
df_test['Btime'].iloc[0] = x
afecta df_test
, pero df_test.iloc[0]['Btime']
podría no. Consulte a continuación para obtener una explicación de por qué. Debido a que una sutil diferencia en el orden de indexación marca una gran diferencia en el comportamiento, es mejor usar 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):
los forma recomendada 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.loc
tiene que convertir las etiquetas de fila y columna en índices posicionales, por lo que se necesita un poco menos de conversión si usa
df.iloc
en lugar de.
df['Btime'].iloc[0] = x
funciona, pero no se recomienda:
Aunque esto funciona, está aprovechando la forma en que los DataFrames son en la actualidad implementado. No hay garantía de que Pandas tenga que funcionar de esta manera en el futuro. En particular, se aprovecha del hecho de que (actualmente) df['Btime']
siempre devuelve una vista (no una copia) por lo que df['Btime'].iloc[n] = x
puede ser usado para asignar un nuevo valor en la enésima ubicación del Btime
columna de df
.
Dado que Pandas no ofrece garantías explícitas sobre cuándo los indexadores devuelven una vista frente a una copia, las asignaciones que utilizan la indexación encadenada generalmente siempre generan una SettingWithCopyWarning
aunque 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'] = x
No funciona:
Por el contrario, la asignación con df.iloc[0]['bar'] = 123
no funciona porque df.iloc[0]
está devolviendo 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: Yo había sugerido previamente df_test.ix[i, 'Btime']
. Pero esto no está garantizado para darle la ith
valor desde ix
intenta indexar por etiqueta antes de intentar indexar por posición. Entonces, si el DataFrame tiene un índice entero que no está ordenado a partir de 0, entonces use ix[i]
devolverá la fila etiquetado i
en lugar del ith
hilera. 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'
Tenga en cuenta que la respuesta de @unutbu será correcta hasta que desee establecer el valor en algo nuevo, entonces no funcionará si su marco de datos es 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)
Otro enfoque que funcionará consistentemente tanto con la configuración como con la obtención es:
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
Otra forma de hacer esto:
first_value = df['Btime'].values[0]
De esta manera parece ser más rápido 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)