Una de esas cosas molestas que todos intentamos entender cuando aprendemos Pandas es la distinción entre .loc
y .iloc
.
Pongamos fin a esta confusión y aclaremos la diferencia entre estos dos métodos. Daré muchos ejemplos, y espero que la distinción sea mucho más clara al final de este blog.
¿Qué son .loc y .iloc en Pandas?
Ambos .loc
y .iloc
son atributos esenciales de los DataFrames de Pandas, y ambos se utilizan para seleccionar subconjuntos específicos de datos. Su propósito es acceder y permitir la manipulación de una parte específica del DataFrame en lugar de todo el DataFrame.
Característica |
.loc |
.iloc |
Sintaxis |
df.loc[indice_fila, indice_columna] |
df.iloc[indice_fila, indice_columna] |
Método de indexación |
Indexación basada en etiquetas |
Indexación basada en posición |
Utilizado para referencia |
Etiquetas de filas y columnas (nombres) |
Índices numéricos de filas y columnas (empezando desde 0) |
Como podemos ver en la tabla, la sintaxis se ve muy similar. La diferencia radica en cómo usamos los argumentos row_indexer
y column_indexer
. Esto se debe a que los dos métodos ofrecen enfoques diferentes para indexar los datos: mientras que .loc
indexa basado en nombres de etiquetas, .iloc
toma los índices de posición numérica de filas y columnas como argumentos.
Examinemos cada uno de los dos métodos en detalle, comenzando con .loc
.
Usando .loc: Selección por Etiquetas
Para ilustrar los conceptos, consideremos una base de datos de clientes hipotética representada por este DataFrame llamado df
, con el ID del Cliente
representando el índice de fila index:
ID del Cliente |
Nombre |
País |
Región |
Edad |
C123 |
John Doe |
Estados Unidos |
América del Norte |
67 |
C234 |
Petra Müller |
Alemania |
Europa |
51 |
C345 |
Ali Khan |
Pakistán |
Asia |
19 |
C456 |
María González |
México |
América del Norte |
26 |
C567 |
David Lee |
China |
Asia |
40 |
Hay cuatro maneras principales de seleccionar filas con .loc
. Estas incluyen:
- Seleccionar una sola fila
- Seleccionando múltiples filas
- Seleccionando un conjunto de filas
- Selección de filas condicional
Seleccionando una sola fila usando .loc
Para seleccionar una sola fila, utilizamos la etiqueta de la fila que queremos recuperar como row_indexer
. Por lo tanto, la sintaxis se ve así: df.loc['row_label']
. Usemos esto para mostrar toda la información sobre nuestro cliente Ali Khan:
df.loc['C345']
C345 |
|
Nombre |
Ali Khan |
País |
Pakistán |
Región |
Asia |
Edad |
19 |
Seleccionando múltiples filas usando .loc
Si queremos seleccionar múltiples filas que no necesariamente siguen un orden entre sí, tenemos que pasar una lista de sus etiquetas de fila como argumento row_indexer
. Esto significa que necesitamos usar no una, sino dos parejas de corchetes: uno para la sintaxis regular de .loc
y otro para la lista de etiquetas.
La línea df.loc[['row_label_1', 'row_label_2']]
devolverá las dos filas del DataFrame df
especificadas en la lista. Digamos que queríamos saber no solo la información sobre Ali Khan sino también sobre David Lee:
df.loc[['C345', 'C567']]
ID de Cliente |
Nombre |
País |
Región |
Edad |
C345 |
Ali Khan |
Pakistan |
Asia |
19 |
C567 |
David Lee |
China |
Asia |
40 |
Seleccionar un conjunto de filas usando .loc
Podemos seleccionar un rango de filas pasando las etiquetas de la primera y última fila con dos puntos entre ellas: df.loc['etiqueta_fila_inicio':'etiqueta_fila_fin']
. Podríamos mostrar las primeras cuatro filas de nuestro DataFrame de esta manera:
df.loc['C123' : 'C456']
Customer ID |
Name |
Country |
Region |
Signup Date |
C123 |
John Doe |
Estados Unidos |
América del Norte |
67 |
C234 |
Petra Müller |
Alemania |
Europa |
51 |
C345 |
Ali Khan |
Pakistán |
Asia |
19 |
C456 |
María González |
México |
América del Norte |
26 |
Hay dos cosas a tener en cuenta aquí:
- La salida incluye la fila especificada en
row_label_end
. Esto es diferente en.iloc
, que cubriremos más adelante. - Solo usamos un par de corchetes cuadrados, aunque queramos recuperar múltiples filas. No usamos una lista para especificar las diversas filas, por lo que usar dos corchetes cuadrados devolvería un
SyntaxError
.
Selección condicional de filas usando .loc
También podemos devolver filas basadas en una expresión condicional. Podemos filtrar todas las filas según si cumplen o no con una cierta condición y mostrar solo las que sí lo hacen.
La sintaxis correspondiente es df.loc[conditional_expression]
, siendo conditional_expression
una declaración sobre los valores permitidos en una columna específica.
Para columnas con datos no numéricos (como Nombre
o País
), la declaración solo puede usar el operador igual o desigual, ya que no hay un orden entre los valores. Por ejemplo, podríamos devolver todas las filas de clientes que no son de Asia:
df.loc[df['Region'] != 'Asia']
ID de Cliente |
Nombre |
País |
Región |
Edad |
C123 |
John Doe |
Estados Unidos |
América del Norte |
67 |
C234 |
Petra Müller |
Alemania |
Europa |
51 |
C456 |
María González |
México |
América del Norte |
26 |
Seleccionando una sola columna usando .loc
Para seleccionar columnas, necesitamos especificar el argumento column_indexer
, que viene después del argumento row_indexer
. Si solo queremos especificar el column_indexer
, debemos de alguna manera marcar que queremos devolver todas las filas y solo filtrar en las columnas. ¡Veamos cómo podemos hacerlo!
Seleccionar una sola columna se puede hacer especificando el column_indexer
con la etiqueta de la columna respectiva. Para recuperar todas las filas, necesitamos especificar el row_indexer
con un simple dos puntos. Llegamos a una sintaxis que se ve así: df.loc[:, 'nombre_columna']
.
Mostremos el Nombre
de cada cliente:
df.loc[:, 'Name']
ID del Cliente |
Nombre |
C123 |
Juan Pérez |
C234 |
Petra Müller |
C345 |
Ali Khan |
C456 |
Maria Gonzalez |
C567 |
David Lee |
Seleccionando múltiples columnas usando .loc
Al igual que al seleccionar múltiples filas, necesitamos pasar una lista de etiquetas de columna si queremos devolver múltiples columnas de un DataFrame que no necesariamente siguen un orden específico: df.loc[:, [col_label_1, 'col_label_2']]
.
Suponiendo que quisiéramos añadir la Edad
de todos los clientes a nuestra última salida, funcionaría así:
df.loc[:, ['Name', 'Age']]
ID del cliente |
Nombre |
Edad |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Seleccionar una serie de columnas usando .loc
Usar dos puntos entre las etiquetas de dos columnas seleccionará todas las columnas en el rango de orden entre las dos columnas especificadas. Es inclusivo de la columna final, lo que significa que la columna llamada col_end
también se seleccionará en la sintaxis estándar, que es la siguiente: df.loc[:, 'col_start':'col_end']
.
Si estuviéramos interesados en el Nombre
, País
y Región
de nuestros clientes, nuestra línea de código podría ser:
df.loc[:, 'Name':'Region']
Identificación del Cliente |
Nombre |
País |
Región |
C123 |
John Doe |
Estados Unidos |
América del Norte |
C234 |
Petra Müller |
Alemania |
Europa |
C345 |
Ali Khan |
Pakistán |
Asia |
C456 |
María González |
México |
América del Norte |
C567 |
David Lee |
China |
Asia |
Selección combinada de filas y columnas usando .loc
También es posible especificar tanto el row_indexer
como el column_indexer
. Esto se podría usar para recuperar una sola pieza de información, es decir, una celda del DataFrame. Para hacer esto, especificamos una fila y una columna usando la sintaxis df.loc['row_label', 'column_name']
.
El caso más útil es devolver un sub-DataFrame que se centra exactamente en el conjunto de filas y columnas que nos interesa. Es posible especificar ambos indexadores como listas usando corchetes, o como un corte usando dos puntos, e incluso combinarlo con una expresión condicional para la selección de filas.
Aquí hay un ejemplo de cómo devolver el Nombre
, País
y Región
de cada cliente con más de 30 años:
df.loc[df['Age'] > 30, 'Name':'Region']
ID de Cliente |
Nombre |
País |
Región |
C123 |
John Doe |
Estados Unidos |
América del Norte |
C234 |
Petra Müller |
Germany |
Europe |
C567 |
David Lee |
China |
Asia |
Usando .iloc: Selección por Posición Entera
.iloc
selecciona por posición en lugar de etiqueta. Esta es la sintaxis estándar de uso de .iloc
: df.iloc[indice_fila, indice_columna]
. Hay dos cosas especiales a tener en cuenta:
- Conteo a partir de 0: La primera fila y columna tienen el índice 0, la segunda tiene el índice 1, etc.
- Exclusividad del valor final del rango: Al usar un rango, la fila o columna especificada después de los dos puntos no se incluye en la selección.
Seleccionar una sola fila utilizando .iloc
Una sola fila se puede seleccionar utilizando el número entero que representa el índice de la fila como el indice_fila
. No necesitamos comillas ya que estamos ingresando un número entero y no una cadena de etiqueta como hicimos con .loc
. Para devolver la primera fila de un DataFrame llamado df
, ingrese df.iloc[0]
.
En nuestro ejemplo de DataFrame, esta línea de código devuelve la información de John Doe:
df.iloc[0]
C123 |
|
Name |
John Doe |
Country |
Estados Unidos |
Región |
América del Norte |
Edad |
67 |
Seleccionar varias filas usando .iloc
Seleccionar varias filas funciona en .iloc
como lo hace en .loc
—ingresamos los índices de fila en una lista con corchetes cuadrados. La sintaxis se ve así: df.iloc[[0, 3, 4]]
.
La salida respectiva en nuestra tabla de clientes se puede ver a continuación:
df.iloc[[0, 3, 4]]
ID de Cliente |
Nombre |
País |
Región |
Edad |
C123 |
John Doe |
Estados Unidos |
América del Norte |
67 |
C456 |
María González |
México |
América del Norte |
26 |
C567 |
David Lee |
China |
Asia |
40 |
Seleccionando un segmento de filas usando .iloc
Para seleccionar un segmento de filas, utilizamos dos enteros de índice de fila especificados separados por dos puntos. Ahora, debemos prestar atención a la exclusividad mencionada anteriormente.
Puedo tomar la línea df.iloc[1:4]
como un ejemplo para ilustrar este concepto. El número de índice 1 significa la segunda fila, por lo que nuestro segmento comienza allí. El entero de índice 4 representa la quinta fila, pero dado que .iloc
no es inclusivo para la selección de segmentos, nuestra salida incluirá todas las filas hasta la última antes de esta. Por lo tanto, devolverá la segunda, tercera y cuarta fila.
Demostremos que la línea funciona como debería:
df.iloc[1:4]
ID de cliente |
Nombre |
País |
Región |
Edad |
C234 |
Petra Müller |
Alemania |
Europa |
51 |
C345 |
Ali Khan |
Pakistán |
Asia |
19 |
C456 |
Maria Gonzalez |
México |
Norteamérica |
26 |
Seleccionar una sola columna usando .iloc
La lógica para seleccionar columnas usando .iloc
sigue lo que hemos aprendido hasta ahora. Veamos cómo funciona para columnas individuales, múltiples columnas y segmentos de columnas.
Al igual que con .loc
, es importante especificar el row_indexer
antes de poder proceder al column_indexer
. Para recuperar los valores de la tercera columna de df
para cada fila, ingresamos df.iloc[:, 2]
.
Como Región
es la tercera columna en nuestro DataFrame, se recuperará como consecuencia de esa línea de código:
df.iloc[:, 2]
ID de Cliente |
Región |
C123 |
América del Norte |
C234 |
Europa |
C345 |
Asia |
C456 |
América del Norte |
C567 |
Asia |
Seleccionar varias columnas usando .iloc
Para seleccionar múltiples columnas que no son necesariamente consecutivas, podemos ingresar una lista que contenga enteros como el column_indexer
. La línea df.iloc[:, [0, 3]]
devuelve tanto la primera como la cuarta columna.
En nuestro caso, la información mostrada es el Nombre
así como la Edad
de cada cliente:
df.iloc[:, [0, 3]]
ID de Cliente |
Nombre |
Edad |
C123 |
John Doe |
67 |
C234 |
Petra Müller |
51 |
C345 |
Ali Khan |
19 |
C456 |
Maria Gonzalez |
26 |
C567 |
David Lee |
40 |
Seleccionar un rango de columnas usando .iloc
Para la selección de slices utilizando .iloc
, la lógica del column_indexer
sigue la misma que la del row_indexer
. La columna representada por el entero después de los dos puntos no se incluye en la salida. Para recuperar la segunda y tercera columnas, la línea de código debe verse así: df.iloc[:, 1:3]
.
Esta línea a continuación devuelve toda la información geográfica que tenemos sobre nuestros clientes:
df.iloc[:, 1:3]
ID del Cliente |
País |
Región |
C123 |
Estados Unidos |
América del Norte |
C234 |
Alemania |
Europa |
C345 |
Pakistán |
Asia |
C456 |
México |
América del Norte |
C567 |
China |
Asia |
Selección combinada de filas y columnas usando .iloc
Podemos juntar lo que aprendimos sobre .iloc
para combinar la selección de filas y columnas. De nuevo, es posible devolver una sola celda o un sub-DataFrame. Para devolver la celda única en la intersección de la fila 3 y la columna 4, ingresamos df.iloc[2, 3]
.
Al igual que con .loc
, podemos especificar ambos indexadores como listas usando los corchetes, o como un rango usando dos puntos. Si queremos seleccionar filas usando expresiones condicionales, eso técnicamente es posible con .iloc
también, pero no se recomienda. Usar los nombres de las etiquetas y .loc
es generalmente mucho más intuitivo y menos propenso a errores.
Este último ejemplo muestra País
, Región
y Edad
para la primera, segunda y quinta fila en nuestro DataFrame:
df.iloc[[0,1,4], 1:4]
ID de Cliente |
País |
Región |
Edad |
C123 |
Estados Unidos |
América del Norte |
67 |
C234 |
Alemania |
Europa |
51 |
C567 |
China |
Asia |
40 |
.iloc vs .loc: Cuándo usar cuál
Generalmente, hay una regla simple donde la elección del método depende de su conocimiento del DataFrame:
- Use
.loc
cuando conozca las etiquetas (nombres) de las filas/columnas. - Utiliza
.iloc
cuando conozcas las posiciones enteras de las filas/columnas.
Algunos escenarios favorecen ya sea .loc
o .iloc
por su naturaleza. Por ejemplo, iterar sobre filas o columnas es más fácil e intuitivo usando enteros que etiquetas. Como ya mencionamos, filtrar filas basándose en condiciones sobre los valores de las columnas es menos propenso a errores utilizando los nombres de las etiquetas de las columnas.
Escenarios que favorecen .loc |
Escenarios que favorecen .iloc |
Tu DataFrame tiene nombres de índice/columnas significativos. |
Estás iterando sobre filas/columnas por su posición. |
Necesitas filtrar en base a condiciones sobre los valores de las columnas. |
Los nombres de índice/columnas no son relevantes para tu tarea. |
Error de clave, Error de nombre y Error de índice con .loc y .iloc
Veamos los problemas posibles. Una trampa común al usar .loc
es encontrar un KeyError
. Este error ocurre cuando intentamos acceder a una etiqueta de fila o columna que no existe dentro de nuestro DataFrame. Para evitar esto, siempre debemos asegurarnos de que las etiquetas que estamos utilizando sean precisas y que coincidan con las etiquetas existentes en tu DataFrame, además de verificar posibles errores tipográficos.
Además, es importante siempre usar comillas para las etiquetas especificadas usando .loc
. Olvidarlas devolverá un NameError
.
Un IndexError
puede ocurrir al usar .iloc
si especificamos una posición entera que está fuera del rango válido de los índices de nuestro DataFrame. Esto sucede cuando el índice al que intentas acceder no existe, ya sea porque está más allá del número de filas o columnas en tu DataFrame o porque es un valor negativo. Para prevenir este error, verifica las dimensiones de tu DataFrame y utiliza valores de índice apropiados dentro del rango válido.
Conclusión
Espero que este blog haya sido útil y que la distinción entre .loc
y .iloc
esté clara hasta ahora. Para aprender más, aquí hay algunos buenos pasos a seguir: