name iloc how example column and python pandas performance indexing lookup

python - how - pandas loc vs. iloc vs. ix vs. at vs. iat?



python loc and iloc (5)

Recientemente comencé a ramificarme desde mi lugar seguro (R) hacia Python y estoy un poco confundido por la localización / selección celular en Pandas . He leído la documentación pero me cuesta entender las implicaciones prácticas de las diversas opciones de localización / selección.

  • ¿Hay alguna razón por la que debería usar .loc o .iloc sobre la opción más general .ix ?
  • Entiendo que .loc , iloc , at e iat pueden proporcionar cierta corrección garantizada que .ix no puede ofrecer, pero también he leído donde .ix tiende a ser la solución más rápida en todos los ámbitos.
  • Por favor, explique el razonamiento de las mejores prácticas del mundo real detrás de la utilización de algo más que .ix ?

Actualizado para pandas 0.20 dado que ix está en desuso. Esto demuestra no solo cómo usar loc , iloc , at , iat , set_value , sino también cómo lograr una indexación mixta basada en posición / etiqueta.

loc - basado en etiquetas
Le permite pasar matrices 1-D como indexadores. Las matrices pueden ser secciones (subconjuntos) del índice o columna, o pueden ser matrices booleanas que tienen la misma longitud que el índice o las columnas.

Nota especial: cuando se pasa un indexador escalar, loc puede asignar un nuevo índice o valor de columna que no existía antes.

# label based, but we can use position values # to get the labels from the index object df.loc[df.index[2], ''ColName''] = 3

df.loc[df.index[1:3], ''ColName''] = 3

iloc - basado en posición
Similar a loc excepto con posiciones en lugar de valores de índice. Sin embargo, no puede asignar nuevas columnas o índices.

# position based, but we can get the position # from the columns object via the `get_loc` method df.iloc[2, df.columns.get_loc(''ColName'')] = 3

df.iloc[2, 4] = 3

df.iloc[:3, 2:4] = 3

at - basado en etiqueta
Funciona muy similar a loc para indexadores escalares. No se puede operar en indexadores de matriz. ¡Lata! Asignar nuevos índices y columnas.

La ventaja sobre loc es que esto es más rápido.
La desventaja es que no puede usar matrices para indexadores.

# label based, but we can use position values # to get the labels from the index object df.at[df.index[2], ''ColName''] = 3

df.at[''C'', ''ColName''] = 3

iat - basado en posición
Funciona de manera similar a iloc . No se puede trabajar en indexadores de matriz. ¡No puedo! Asignar nuevos índices y columnas.

La ventaja sobre iloc es que esto es más rápido.
La desventaja es que no puede usar matrices para indexadores.

# position based, but we can get the position # from the columns object via the `get_loc` method IBM.iat[2, IBM.columns.get_loc(''PNL'')] = 3

set_value : basado en etiquetas
Funciona muy similar a loc para indexadores escalares. No se puede operar en indexadores de matriz. ¡Lata! asignar nuevos índices y columnas

Ventaja ¡ Súper rápido, porque hay muy poca sobrecarga!
Desventaja Hay muy pocos gastos generales porque los pandas no están haciendo un montón de controles de seguridad. Use bajo su propio riesgo . Además, esto no está destinado al uso público.

# label based, but we can use position values # to get the labels from the index object df.set_value(df.index[2], ''ColName'', 3)

set_value - basado en la posición
Funciona de manera similar a iloc . No se puede trabajar en indexadores de matriz. ¡No puedo! Asignar nuevos índices y columnas.

Ventaja ¡ Súper rápido, porque hay muy poca sobrecarga!
Desventaja Hay muy pocos gastos generales porque los pandas no están haciendo un montón de controles de seguridad. Use bajo su propio riesgo . Además, esto no está destinado al uso público.

# position based, but we can get the position # from the columns object via the `get_loc` method df.set_value(2, df.columns.get_loc(''ColName''), 3, takable=True)


Comencemos con este pequeño df:

import pandas as pd import time as tm import numpy as np n=10 a=np.arange(0,n**2) df=pd.DataFrame(a.reshape(n,n))

Así que tendremos

df Out[25]: 0 1 2 3 4 5 6 7 8 9 0 0 1 2 3 4 5 6 7 8 9 1 10 11 12 13 14 15 16 17 18 19 2 20 21 22 23 24 25 26 27 28 29 3 30 31 32 33 34 35 36 37 38 39 4 40 41 42 43 44 45 46 47 48 49 5 50 51 52 53 54 55 56 57 58 59 6 60 61 62 63 64 65 66 67 68 69 7 70 71 72 73 74 75 76 77 78 79 8 80 81 82 83 84 85 86 87 88 89 9 90 91 92 93 94 95 96 97 98 99

Con esto tenemos:

df.iloc[3,3] Out[33]: 33 df.iat[3,3] Out[34]: 33 df.iloc[:3,:3] Out[35]: 0 1 2 3 0 0 1 2 3 1 10 11 12 13 2 20 21 22 23 3 30 31 32 33 df.iat[:3,:3] Traceback (most recent call last): ... omissis ... ValueError: At based indexing on an integer index can only have integer indexers

Por lo tanto, no podemos usar .iat para el subconjunto, donde solo debemos usar .iloc.

Pero intentemos seleccionar entre un df más grande y verifiquemos la velocidad ...

# -*- coding: utf-8 -*- """ Created on Wed Feb 7 09:58:39 2018 @author: Fabio Pomi """ import pandas as pd import time as tm import numpy as np n=1000 a=np.arange(0,n**2) df=pd.DataFrame(a.reshape(n,n)) t1=tm.time() for j in df.index: for i in df.columns: a=df.iloc[j,i] t2=tm.time() for j in df.index: for i in df.columns: a=df.iat[j,i] t3=tm.time() loc=t2-t1 at=t3-t2 prc = loc/at *100 print(''/nloc:%f at:%f prc:%f'' %(loc,at,prc)) loc:10.485600 at:7.395423 prc:141.784987

Entonces, con .loc podemos administrar subconjuntos y con .at solo un escalar, pero .at es más rápido que .loc

:-)


Hay dos formas principales en que los pandas hacen selecciones de un DataFrame.

  • Por etiqueta
  • Por ubicación entera

La documentación utiliza el término posición para referirse a la ubicación de enteros . No me gusta esta terminología porque siento que es confusa. La ubicación de enteros es más descriptiva y es exactamente lo que representa .iloc . La palabra clave aquí es INTEGER : debe usar enteros al seleccionar por ubicación de enteros.

Antes de mostrar el resumen, asegurémonos de que ...

.ix está en desuso y es ambiguo y nunca debe usarse

Hay tres indexadores principales para los pandas. Tenemos el operador de indexación en sí (los corchetes [] ), .loc y .iloc . Resumamos ellos:

  • [] - Principalmente selecciona subconjuntos de columnas, pero también puede seleccionar filas. No se pueden seleccionar simultáneamente filas y columnas.
  • .loc : selecciona subconjuntos de filas y columnas solo por etiqueta
  • .iloc : selecciona subconjuntos de filas y columnas solo por ubicación entera

Casi nunca uso .at o .iat ya que no agregan funcionalidad adicional y con solo un pequeño aumento de rendimiento. Desalentaría su uso a menos que tenga una aplicación muy urgente. En cualquier caso, tenemos su resumen:

  • .at selecciona un solo valor escalar en el DataFrame por etiqueta solamente
  • .iat selecciona un solo valor escalar en el DataFrame solo por ubicación entera

Además de la selección por etiqueta y ubicación de enteros, existe una selección booleana también conocida como indexación booleana .

A .iat se muestran ejemplos que explican .loc , .iloc , selección booleana y .at y .iat

Primero nos centraremos en las diferencias entre .loc y .iloc . Antes de hablar sobre las diferencias, es importante comprender que los marcos de datos tienen etiquetas que ayudan a identificar cada columna y cada fila. Echemos un vistazo a un DataFrame de muestra:

df = pd.DataFrame({''age'':[30, 2, 12, 4, 32, 33, 69], ''color'':[''blue'', ''green'', ''red'', ''white'', ''gray'', ''black'', ''red''], ''food'':[''Steak'', ''Lamb'', ''Mango'', ''Apple'', ''Cheese'', ''Melon'', ''Beans''], ''height'':[165, 70, 120, 80, 180, 172, 150], ''score'':[4.6, 8.3, 9.0, 3.3, 1.8, 9.5, 2.2], ''state'':[''NY'', ''TX'', ''FL'', ''AL'', ''AK'', ''TX'', ''TX''] }, index=[''Jane'', ''Nick'', ''Aaron'', ''Penelope'', ''Dean'', ''Christina'', ''Cornelia''])

Todas las palabras en negrita son las etiquetas. Las etiquetas, age , color , food , height , score y state se utilizan para las columnas . Las otras etiquetas, Jane , Nick , Aaron , Penelope , Dean , Christina , Cornelia se utilizan como etiquetas para las filas. Colectivamente, estas etiquetas de fila se conocen como el índice .

Las formas principales de seleccionar filas particulares en un DataFrame son con los .loc y .iloc . Cada uno de estos indexadores también se puede usar para seleccionar columnas simultáneamente, pero por ahora es más fácil centrarse en las filas. Además, cada uno de los indexadores utiliza un conjunto de corchetes que siguen inmediatamente a su nombre para realizar sus selecciones.

.loc selecciona datos solo por etiquetas

Primero hablaremos sobre el indexador .loc que solo selecciona datos por las etiquetas de índice o columna. En nuestro DataFrame de muestra, proporcionamos nombres significativos como valores para el índice. Muchos DataFrames no tendrán nombres significativos y, por el contrario, solo usarán los enteros de 0 a n-1, donde n es la longitud (número de filas) del DataFrame.

Hay muchas entradas diferentes que puede usar para .loc tres de ellas son

  • Una cuerda
  • Una lista de cadenas
  • Corte la notación utilizando cadenas como valores iniciales y finales

Seleccionar una sola fila con .loc con una cadena

Para seleccionar una sola fila de datos, coloque la etiqueta de índice dentro de los corchetes después de .loc .

df.loc[''Penelope'']

Esto devuelve la fila de datos como una serie

age 4 color white food Apple height 80 score 3.3 state AL Name: Penelope, dtype: object

Seleccionar varias filas con .loc con una lista de cadenas

df.loc[[''Cornelia'', ''Jane'', ''Dean'']]

Esto devuelve un DataFrame con las filas en el orden especificado en la lista:

Seleccionar varias filas con .loc con notación de corte

La notación de corte se define mediante valores de inicio, parada y paso. Al cortar por etiqueta, los pandas incluyen el valor de detención en el retorno. Los siguientes cortes de Aaron a Dean, inclusive. Su tamaño de paso no está definido explícitamente sino que está predeterminado en 1.

df.loc[''Aaron'':''Dean'']

Los cortes complejos se pueden tomar de la misma manera que las listas de Python.

.iloc selecciona datos solo por ubicación entera

Pasemos ahora a .iloc . Cada fila y columna de datos en un DataFrame tiene una ubicación entera que lo define. Esto se suma a la etiqueta que se muestra visualmente en la salida. La ubicación entera es simplemente el número de filas / columnas desde la parte superior / izquierda que comienza en 0.

Hay muchas entradas diferentes que puede usar para .iloc tres de ellas son

  • Un entero
  • Una lista de enteros
  • Corte la notación usando enteros como valores de inicio y parada

Seleccionar una sola fila con .iloc con un entero

df.iloc[4]

Esto devuelve la quinta fila (ubicación entera 4) como una serie

age 32 color gray food Cheese height 180 score 1.8 state AK Name: Dean, dtype: object

Seleccionar varias filas con .iloc con una lista de enteros

df.iloc[[2, -2]]

Esto devuelve un DataFrame de la tercera y la penúltima fila:

Selección de varias filas con .iloc con notación de corte

df.iloc[:5:3]

Selección simultánea de filas y columnas con .loc y .iloc

Una excelente capacidad de ambos .loc/.iloc es su capacidad para seleccionar tanto filas como columnas simultáneamente. En los ejemplos anteriores, todas las columnas fueron devueltas de cada selección. Podemos elegir columnas con los mismos tipos de entradas que para las filas. Simplemente necesitamos separar la selección de fila y columna con una coma .

Por ejemplo, podemos seleccionar las filas Jane y Dean con solo la altura de las columnas, la puntuación y el estado de esta manera:

df.loc[[''Jane'', ''Dean''], ''height'':]

Esto utiliza una lista de etiquetas para las filas y la notación de corte para las columnas.

Naturalmente, podemos hacer operaciones similares con .iloc usando solo enteros.

df.iloc[[1,4], 2] Nick Lamb Dean Cheese Name: food, dtype: object

Selección simultánea con etiquetas y ubicación de enteros

.ix se usó para hacer selecciones simultáneamente con etiquetas y ubicación de números enteros, lo cual fue útil pero confuso y ambiguo a veces y, afortunadamente, ha quedado en desuso. En el caso de que necesite hacer una selección con una combinación de etiquetas y ubicaciones de enteros, deberá realizar tanto las etiquetas de selección como las ubicaciones de enteros.

Por ejemplo, si queremos seleccionar las filas Nick y Cornelia junto con las columnas 2 y 4, podríamos usar .loc al convertir los enteros en etiquetas con lo siguiente:

col_names = df.columns[[2, 4]] df.loc[[''Nick'', ''Cornelia''], col_names]

O, alternativamente, convierta las etiquetas de índice a enteros con el método de índice get_loc .

labels = [''Nick'', ''Cornelia''] index_ints = [df.index.get_loc(label) for label in labels] df.iloc[index_ints, [2, 4]]

Selección booleana

El indexador .loc también puede hacer una selección booleana. Por ejemplo, si estamos interesados ​​en encontrar todas las filas donde la edad es superior a 30 y devolver solo las columnas de food y score , podemos hacer lo siguiente:

df.loc[df[''age''] > 30, [''food'', ''score'']]

Puede replicar esto con .iloc pero no puede pasarle una serie booleana. Debe convertir la serie booleana en una matriz numpy como esta:

df.iloc[(df[''age''] > 30).values, [2, 4]]

Seleccionar todas las filas

Es posible usar .loc/.iloc solo para la selección de columnas. Puede seleccionar todas las filas utilizando dos puntos como este:

df.loc[:, ''color'':''score'':2]

El operador de indexación, [] , puede dividir puede seleccionar filas y columnas también, pero no simultáneamente.

La mayoría de las personas están familiarizadas con el propósito principal del operador de indexación DataFrame, que es seleccionar columnas. Una cadena selecciona una sola columna como Serie y una lista de cadenas selecciona varias columnas como un Marco de datos.

df[''food''] Jane Steak Nick Lamb Aaron Mango Penelope Apple Dean Cheese Christina Melon Cornelia Beans Name: food, dtype: object

Usar una lista selecciona múltiples columnas

df[[''food'', ''score'']]

Con lo que las personas están menos familiarizadas es que, cuando se utiliza la notación de corte, la selección se realiza por etiquetas de fila o por ubicación entera. Esto es muy confuso y es algo que casi nunca uso, pero funciona.

df[''Penelope'':''Christina''] # slice rows by label

df[2:6:2] # slice rows by integer location

La .loc/.iloc de .loc/.iloc para seleccionar filas es altamente preferida. El operador de indexación solo no puede seleccionar filas y columnas simultáneamente.

df[3:5, ''color''] TypeError: unhashable type: ''slice''

Selección por .at y .iat

La selección con .at es casi idéntica a .loc pero solo selecciona una ''celda'' en su DataFrame. Normalmente nos referimos a esta celda como un valor escalar. Para usar .at , .at una etiqueta de fila y columna separada por una coma.

df.at[''Christina'', ''color''] ''black''

La selección con .iat es casi idéntica a .iloc pero solo selecciona un único valor escalar. Debe pasarle un número entero para las ubicaciones de fila y columna

df.iat[2, 5] ''FL''



df = pd.DataFrame({''A'':[''a'', ''b'', ''c''], ''B'':[54, 67, 89]}, index=[100, 200, 300]) df A B 100 a 54 200 b 67 300 c 89 In [19]: df.loc[100] Out[19]: A a B 54 Name: 100, dtype: object In [20]: df.iloc[0] Out[20]: A a B 54 Name: 100, dtype: object In [24]: df2 = df.set_index([df.index,''A'']) df2 Out[24]: B A 100 a 54 200 b 67 300 c 89 In [25]: df2.ix[100, ''a''] Out[25]: B 54 Name: (100, a), dtype: int64