¿Cómo son diferentes iloc, ix y loc?

¿Alguien puede explicar cómo estos tres métodos de corte son diferentes?
He visto los documentos y he visto estas respuestas , pero todavía no puedo explicar en qué se diferencian los tres. Para mí, parecen intercambiables en gran parte, porque están en los niveles más bajos de corte.

Por ejemplo, digamos que queremos obtener las primeras cinco filas de un DataFrame . ¿Cómo es que estos tres funcionan?

 df.loc[:5] df.ix[:5] df.iloc[:5] 

¿Puede alguien presentar tres casos donde la distinción en usos es más clara?

Nota: en pandas versión 0.20.0 y superior, ix está en desuso y se recomienda el uso de loc e iloc . He dejado las partes de esta respuesta que describen ix intacto como referencia para los usuarios de versiones anteriores de pandas. A continuación se han agregado ejemplos que muestran alternativas a ix .


Primero, aquí hay un resumen de los tres métodos:

  • loc obtiene filas (o columnas) con tags particulares del índice.
  • iloc obtiene filas (o columnas) en posiciones particulares en el índice (por lo que solo toma números enteros).
  • ix generalmente intenta comportarse como loc pero vuelve a comportarse como iloc si una etiqueta no está presente en el índice.

Es importante tener en cuenta algunas sutilezas que pueden hacer que ix poco difícil de usar:

  • Si el índice es de tipo entero, ix solo utilizará la indexación basada en tags y no volverá a la indexación basada en la posición. Si la etiqueta no está en el índice, se genera un error.

  • Si el índice no contiene solo números enteros, entonces, dado un entero, ix utilizará de inmediato la indexación basada en la posición en lugar de la indexación basada en tags. Sin embargo, si a ix se le asigna otro tipo (por ejemplo, una cadena), puede utilizar la indexación basada en tags.


Para ilustrar las diferencias entre los tres métodos, considere la siguiente serie:

 >>> s = pd.Series(np.nan, index=[49,48,47,46,45, 1, 2, 3, 4, 5]) >>> s 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN 4 NaN 5 NaN 

Veremos el corte con el valor entero 3 .

En este caso, s.iloc[:3] nos devuelve las primeras 3 filas (ya que trata a 3 como una posición) y s.loc[:3] nos devuelve las primeras 8 filas (ya que trata a 3 como una etiqueta):

 >>> s.iloc[:3] # slice the first three rows 49 NaN 48 NaN 47 NaN >>> s.loc[:3] # slice up to and including label 3 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN >>> s.ix[:3] # the integer is in the index so s.ix[:3] works like loc 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN 2 NaN 3 NaN 

El aviso s.ix[:3] devuelve la misma serie que s.loc[:3] ya que busca la etiqueta primero en lugar de trabajar en la posición (y el índice para s es de tipo entero).

¿Qué pasa si intentamos con una etiqueta entera que no está en el índice (digamos 6 )?

Aquí s.iloc[:6] devuelve las primeras 6 filas de la Serie como se esperaba. Sin embargo, s.loc[:6] genera un error KeyError ya que 6 no está en el índice.

 >>> s.iloc[:6] 49 NaN 48 NaN 47 NaN 46 NaN 45 NaN 1 NaN >>> s.loc[:6] KeyError: 6 >>> s.ix[:6] KeyError: 6 

Según las sutilezas mencionadas anteriormente, s.ix[:6] ahora genera un KeyError porque intenta funcionar como loc pero no puede encontrar un 6 en el índice. Debido a que nuestro índice es de tipo entero, ix no vuelve a comportarse como iloc .

Sin embargo, si nuestro índice fuera de tipo mixto, dado un entero, ix se comportaría como iloc inmediatamente en lugar de generar un KeyError:

 >>> s2 = pd.Series(np.nan, index=['a','b','c','d','e', 1, 2, 3, 4, 5]) >>> s2.index.is_mixed() # index is mix of different types True >>> s2.ix[:6] # now behaves like iloc given integer a NaN b NaN c NaN d NaN e NaN 1 NaN 

Tenga en cuenta que ix todavía puede aceptar no enteros y comportarse como loc :

 >>> s2.ix[:'c'] # behaves like loc given non-integer a NaN b NaN c NaN 

Como consejo general, si solo está indexando usando tags, o solo indexando usando posiciones enteras, iloc con loc o iloc para evitar resultados inesperados – intente no usar ix .


Combinación de indexación basada en posición y etiqueta.

A veces, dado un dataframe, deseará mezclar métodos de indexación de tags y posicionales para las filas y columnas.

Por ejemplo, considere el siguiente DataFrame. ¿Cuál es la mejor manera de dividir las filas hasta e incluir ‘c’ y tomar las primeras cuatro columnas?

 >>> df = pd.DataFrame(np.nan, index=list('abcde'), columns=['x','y','z', 8, 9]) >>> df xyz 8 9 a NaN NaN NaN NaN NaN b NaN NaN NaN NaN NaN c NaN NaN NaN NaN NaN d NaN NaN NaN NaN NaN e NaN NaN NaN NaN NaN 

En versiones anteriores de pandas (antes de 0.20.0) ix permite hacer esto de manera ordenada: podemos dividir las filas por etiqueta y las columnas por posición (tenga en cuenta que para las columnas, ix se establecerá de manera predeterminada en el corte basado en posición, ya que 4 no es un nombre de columna):

 >>> df.ix[:'c', :4] xyz 8 a NaN NaN NaN NaN b NaN NaN NaN NaN c NaN NaN NaN NaN 

En versiones posteriores de pandas, podemos lograr este resultado utilizando iloc y la ayuda de otro método:

 >>> df.iloc[:df.index.get_loc('c') + 1, :4] xyz 8 a NaN NaN NaN NaN b NaN NaN NaN NaN c NaN NaN NaN NaN 

get_loc() es un método de índice que significa “obtener la posición de la etiqueta en este índice”. Tenga en cuenta que dado que cortar con iloc es exclusivo de su punto final, debemos agregar 1 a este valor si también queremos la fila ‘c’.

Hay más ejemplos en la documentación de los pandas aquí .

iloc trabaja basado en posicionamiento entero. Así que no importa cuáles sean las tags de sus filas, siempre puede, por ejemplo, obtener la primera fila haciendo

 df.iloc[0] 

o las últimas cinco filas haciendo

 df.iloc[-5:] 

También puedes usarlo en las columnas. Esto recupera la tercera columna:

 df.iloc[:, 2] # the : in the first position indicates all rows 

Puedes combinarlos para obtener intersecciones de filas y columnas:

 df.iloc[:3, :3] # The upper-left 3 X 3 entries (assuming df has 3+ rows and columns) 

Por otro lado, .loc utiliza índices denominados. Vamos a configurar un dataframe con cadenas como tags de fila y columna:

 df = pd.DataFrame(index=['a', 'b', 'c'], columns=['time', 'date', 'name']) 

Entonces podemos obtener la primera fila por

 df.loc['a'] # equivalent to df.iloc[0] 

y las segundas dos filas de la columna 'date' por

 df.loc['b':, 'date'] # equivalent to df.iloc[1:, 1] 

y así. Ahora, probablemente vale la pena señalar que los índices de fila y columna predeterminados para un DataFrame son números enteros de 0 y en este caso, iloc y loc funcionarán de la misma manera. Por eso tus tres ejemplos son equivalentes. Si tuviera un índice no numérico, como cadenas o df.loc[:5] , df.loc[:5] generaría un error.

Además, puede realizar la recuperación de columnas simplemente utilizando el __getitem__ del dataframe:

 df['time'] # equivalent to df.loc[:, 'time'] 

Ahora suponga que desea mezclar la posición y la indexación con nombre, es decir, la indexación utilizando nombres en filas y posiciones en columnas (para aclarar, me refiero a seleccionar de nuestro dataframe, en lugar de crear un dataframe con cadenas en el índice de fila y enteros en el índice de la columna). Aquí es donde entra el .ix :

 df.ix[:2, 'time'] # the first two rows of the 'time' column 

Creo que también vale la pena mencionar que también puedes pasar vectores booleanos al método loc . Por ejemplo:

  b = [True, False, True] df.loc[b] 

Volverá la 1ª y 3ª fila de df . Esto es equivalente a df[b] para la selección, pero también se puede usar para la asignación a través de vectores booleanos:

 df.loc[b, 'name'] = 'Mary', 'John' 

En mi opinión, la respuesta aceptada es confusa, ya que utiliza un DataFrame con solo valores faltantes. Tampoco me gusta el término basado en la posición para .iloc y, en cambio, prefiero la ubicación de enteros, ya que es mucho más descriptivo y exactamente lo que significa .iloc . La palabra clave es INTEGER – .iloc necesita INTEGERS.

Ver mi serie de blog extremadamente detallada sobre la selección de subconjuntos para más


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

Como .ix está en desuso, solo nos enfocaremos en las diferencias entre .loc y .iloc .

Antes de hablar sobre las diferencias, es importante comprender que los DataFrames tienen tags que ayudan a identificar cada columna y cada índice. 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']) 

introduzca la descripción de la imagen aquí

Todas las palabras en negrita son las tags. Las tags, age , color , food , height , score y state se utilizan para las columnas . Las otras tags, Jane , Nick , Aaron , Penelope , Dean , Christina , Cornelia se utilizan para el índice .


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

.loc selecciona datos solo por tags

Primero hablaremos sobre el indexador .loc que solo selecciona datos por el índice o las tags de columna. En nuestro DataFrame de muestra, proporcionamos nombres significativos como valores para el índice. Muchos DataFrames no tendrán nombres significativos y, en su lugar, predeterminarán solo los números enteros de 0 a n-1, donde n es la longitud del DataFrame.

Hay tres entradas diferentes que puedes usar para .loc

  • Una cuerda
  • Una lista de cuerdas
  • Corte de notación usando cadenas como los valores de inicio y parada.

Seleccionando una sola fila con .loc con una cadena

Para seleccionar una sola fila de datos, coloque la etiqueta de índice dentro de los corchetes que siguen a .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 

Seleccionando múltiples 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:

introduzca la descripción de la imagen aquí

Seleccionando múltiples filas con .loc con notación de segmento

La notación de corte se define mediante los valores de inicio, parada y paso. Cuando se corta por etiqueta, pandas incluye el valor de parada en la devolución. Las siguientes rebanadas de Aaron a Dean, inclusive. El tamaño de su paso no está definido explícitamente, pero está predeterminado en 1.

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

introduzca la descripción de la imagen aquí

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

.iloc selecciona datos solo por ubicación de enteros

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

Hay tres entradas diferentes que puedes usar para .iloc

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

Seleccionando una sola fila con .iloc con un entero

 df.iloc[4] 

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

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

Seleccionando múltiples filas con .iloc con una lista de enteros

 df.iloc[[2, -2]] 

Esto devuelve un DataFrame de la tercera y segunda a las últimas filas:

introduzca la descripción de la imagen aquí

Seleccionando múltiples filas con .iloc con notación de corte

 df.iloc[:5:3] 

introduzca la descripción de la imagen aquí


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

Una excelente capacidad de ambos .loc/.iloc es su capacidad para seleccionar filas y columnas simultáneamente. En los ejemplos anteriores, todas las columnas se devolvieron de cada selección. Podemos elegir columnas con los mismos tipos de entradas que hacemos para las filas. Simplemente necesitamos separar la selección de filas y columnas 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':] 

introduzca la descripción de la imagen aquí

Esto utiliza una lista de tags para las filas y notación de división para las columnas

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

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

Selección simultánea con tags y localización de enteros.

.ix se usó para hacer selecciones simultáneamente con tags y ubicación de enteros que fue útil pero confuso y ambiguo a veces y afortunadamente ha sido desaprobado. En el caso de que necesite realizar una selección con una combinación de tags y ubicaciones de enteros, deberá realizar ambas tags de selecciones o 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 tags con lo siguiente:

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

O alternativamente, convierta las tags de índice en 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 selección booleana. Por ejemplo, si estamos interesados ​​en encontrar todas las filas en las que 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. Debes convertir la serie booleana en una matriz numpy como esta:

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

Seleccionando todas las filas

Es posible usar .loc/.iloc solo para la selección de la columna. Puedes seleccionar todas las filas usando dos puntos como este:

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

introduzca la descripción de la imagen aquí


El operador de indexación, [] , 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 de 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 

Usando una lista selecciona múltiples columnas

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

introduzca la descripción de la imagen aquí

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

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

introduzca la descripción de la imagen aquí

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

introduzca la descripción de la imagen aquí

La .loc/.iloc explícita 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' 

Déjenme decirles que ix estaba en las versiones anteriores de pandas. E iloc y loc están incorporadas en sus últimas versiones.

  • IX: esto se usa para analizar cualquier dato en particular del dataframe usando la etiqueta o el índice de fila y columna a la vez. Por lo tanto, se generó un pequeño problema, como en algunos casos donde el índice de columna y el índice de fila eran la combinación de número y tags de cadena.
    Ejemplo: – df.ix[:2, 'time']

Ahora ven a loc.

  • Esto analiza los datos utilizando las tags como índice, ya sea columna o fila.
    Ejemplo: – df.loc[:, 'color':'score':2]

Ahora para iloc.

  • Lo que hacemos es proporcionar tanto la columna como la fila como índice (indicado por el número)
    Ejemplo: – df.iloc[[1,4], 2]