tutorial index functions from espaƱol create python pandas dataframe

python - index - pandas.at versus.loc



pandas python (2)

A medida que preguntaste acerca de las limitaciones de .at , aquí hay una cosa con la que me topé recientemente (usar pandas 0.22). Usemos el ejemplo de la documentación :

df = pd.DataFrame([[0, 2, 3], [0, 4, 1], [10, 20, 30]], index=[4, 5, 6], columns=[''A'', ''B'', ''C'']) df2 = df.copy() A B C 4 0 2 3 5 0 4 1 6 10 20 30

Si ahora hago

df.at[4, ''B''] = 100

el resultado se ve como se esperaba

A B C 4 0 100 3 5 0 4 1 6 10 20 30

Sin embargo, cuando trato de hacer

df.at[4, ''C''] = 10.05

Parece que .at intenta conservar el tipo de datos (aquí: int ) :

A B C 4 0 100 10 5 0 4 1 6 10 20 30

Eso parece ser una diferencia para .loc :

df2.loc[4, ''C''] = 10.05

cede lo deseado

A B C 4 0 2 10.05 5 0 4 1.00 6 10 20 30.00

Lo arriesgado en el ejemplo anterior es que sucede en silencio (la conversión de float a int`). Cuando uno intente lo mismo con las cadenas, lanzará un error:

df.at[5, ''A''] = ''a_string''

ValueError: literal no válido para int () con base 10: ''a_string''

He estado explorando cómo optimizar mi código y me encontré con el método .at pandas . Por la documentation

Acceso escalar basado en etiquetas rápidas

Al igual que en loc, at proporciona búsquedas escalares basadas en etiquetas. También puede establecer utilizando estos indexadores.

Así que corrí algunas muestras:

Preparar

import pandas as pd import numpy as np from string import letters, lowercase, uppercase lt = list(letters) lc = list(lowercase) uc = list(uppercase) def gdf(rows, cols, seed=None): """rows and cols are what you''d pass to pd.MultiIndex.from_product()""" gmi = pd.MultiIndex.from_product df = pd.DataFrame(index=gmi(rows), columns=gmi(cols)) np.random.seed(seed) df.iloc[:, :] = np.random.rand(*df.shape) return df seed = [3, 1415] df = gdf([lc, uc], [lc, uc], seed) print df.head().T.head().T

df parece a

a A B C D E a A 0.444939 0.407554 0.460148 0.465239 0.462691 B 0.032746 0.485650 0.503892 0.351520 0.061569 C 0.777350 0.047677 0.250667 0.602878 0.570528 D 0.927783 0.653868 0.381103 0.959544 0.033253 E 0.191985 0.304597 0.195106 0.370921 0.631576

Vamos a usar .at y .loc y asegurar que obtengo lo mismo

print "using .loc", df.loc[(''a'', ''A''), (''c'', ''C'')] print "using .at ", df.at[(''a'', ''A''), (''c'', ''C'')] using .loc 0.37374090276 using .at 0.37374090276

Velocidad de prueba usando .loc

%%timeit df.loc[(''a'', ''A''), (''c'', ''C'')] 10000 loops, best of 3: 180 µs per loop

Velocidad de prueba usando .at

%%timeit df.at[(''a'', ''A''), (''c'', ''C'')] The slowest run took 6.11 times longer than the fastest. This could mean that an intermediate result is being cached. 100000 loops, best of 3: 8 µs per loop

Esto parece ser un gran aumento de velocidad. Incluso en la etapa de almacenamiento en caché 6.11 * 8 es mucho más rápido que 180

Pregunta

¿Cuáles son las limitaciones de .at ? Estoy motivado para usarlo. La documentación dice que es similar a .loc pero no se comporta de manera similar. Ejemplo:

# small df sdf = gdf([lc[:2]], [uc[:2]], seed) print sdf.loc[:, :] A B a 0.444939 0.407554 b 0.460148 0.465239

donde como print sdf.at[:, :] da como resultado TypeError: unhashable type

Así que obviamente no es lo mismo, incluso si la intención es ser similar.

Dicho esto, ¿quién puede proporcionar orientación sobre qué se puede y no se puede hacer con el método .at ?


Actualización: df.get_value está en desuso a partir de la versión 0.21.0. El uso de df.at o df.iat es el método recomendado para seguir adelante.

df.at solo puede acceder a un único valor a la vez.

df.loc puede seleccionar múltiples filas y / o columnas.

Tenga en cuenta que también hay df.get_value , que puede ser incluso más rápido para acceder a valores individuales:

In [25]: %timeit df.loc[(''a'', ''A''), (''c'', ''C'')] 10000 loops, best of 3: 187 µs per loop In [26]: %timeit df.at[(''a'', ''A''), (''c'', ''C'')] 100000 loops, best of 3: 8.33 µs per loop In [35]: %timeit df.get_value((''a'', ''A''), (''c'', ''C'')) 100000 loops, best of 3: 3.62 µs per loop

Debajo del capó, df.at[...] llama a df.get_value , pero también realiza una comprobación de tipo de las teclas.