Pandas práctico(2): Selección, Filtrado, loc e iloc

En el último artículo, aprendimos sobre las dos estructuras de datos básicas de pandas: Series y DataFrames. También construimos un par por nuestra cuenta y aprendimos los conceptos básicos de indexación y selección.

Hoy aprenderemos un poco más sobre seleccionar y filtrar elementos de las estructuras de datos de Pandas. Esto puede parecer un tema increíblemente básico, pero es muy útil. Por eso es importante entenderlo bien antes de abordar temas más avanzados.

Saber cómo manipular datos es una de las habilidades más importantes para cualquiera que trabaje en ciencia de datos y aprendizaje automático, y la base de esas habilidades es la selección y filtrado de datos.

¡Bien, comencemos!

Jugando con Series

Seleccionar elementos de un objeto Series es bastante directo, los siguientes son ejemplos de diferentes formas de seleccionar elementos de una serie pequeña de 8 elementos

import pandas as pd
import numpy as np

ser = pd.Series(np.arange(8), index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
print(ser)
a    0
b    1
c    2
d    3
e    4
f    5
g    6
h    7
dtype: int64
# Puedes seleccionar elementos de una serie usando su índice
ser['d']
3
# También puedes pasar una lista de elementos de índice si necesitas recuperar más de un elemento
ser[['a', 'd', 'g']]
a    0
d    3
g    6
dtype: int64

¡Pandas es tan genial que incluso te deja hacer selección de slices basadas en índices! Hay una distinción importante entre esto y los slices regulares: El último elemento del slice está incluido.

# Selecciona todos los elementos de b a g (ambos extremos incluidos)
ser['b':'g']
b    1
c    2
d    3
e    4
f    5
g    6
dtype: int64

El hecho de que no estés usando el índice por defecto no significa que la selección basada en posición no esté permitida. Todavía puedes seleccionar elementos de una Serie usando enteros.

# Selecciona el tercero (índice 2, ¿recuerdas? 0-indexado) de nuestra serie
ser[2]
2
# Ahora, selecciona los elementos en los índices 2, 3 y 6
ser[[2,3,6]]
c    2
d    3
g    6
dtype: int64
# Y finalmente, la selección por slices todavía está disponible (pero en este caso, el último elemento es excluido como de costumbre)
ser[2:8]
c    2
d    3
e    4
f    5
g    6
h    7
dtype: int64

Jugando con DataFrames

Debido a una dimensión extra, seleccionar elementos de DataFrames es más complejo que de Series. Comenzaremos con el escenario más básico: Seleccionar columnas completas.

pokedata = {'Name': ['Abra', 'Koffing', 'Milcery', 'Pikachu', 'Shellder', 'Vulpix'],
            'Type': ['Psychic', 'Poison', 'Fairy', 'Electric', 'Water', 'Fire'],
            'HP': [25, 40, 45, 35, 30, 38],
            'Speed': [90, 35, 34, 90, 40, 65],
            'Color': ['Yellow', 'Purple', 'White', 'Yellow', 'Purple', 'Red'],
            'FirstGen': [True, True, False, True, True, True]}

# Usaremos la columna Name como índice
pframe = pd.DataFrame(pokedata).set_index('Name')
pframe
Name Type HP Speed Color FirstGen
Abra Psychic 25 90 Yellow True
Koffing Poison 40 35 Purple True
Milcery Fairy 45 34 White False
Pikachu Electric 35 90 Yellow True
Shellder Water 30 40 Purple True
Vulpix Fire 38 65 Red True
# Puedes seleccionar una columna del frame pasando el nombre entre corchetes
pframe['Type']
Name
Abra         Psychic
Koffing       Poison
Milcery        Fairy
Pikachu     Electric
Shellder       Water
Vulpix          Fire
Name: Type, dtype: object
# Si pasas una lista de nombres de columnas las recuperarás en ese orden
pframe[['FirstGen', 'HP', 'Color']]
Name FirstGen HP Color
Abra True 25 Yellow
Koffing True 40 Purple
Milcery False 45 White
Pikachu True 35 Yellow
Shellder True 30 Purple
Vulpix True 38 Red

Los corchetes también soportan selección basada en contenido. Seleccionemos filas que satisfacen criterios específicos para ver cómo funciona.

# Selecciona todos los Pokemon con velocidad menor a 50
pframe[pframe['Speed'] < 50]
Name Type HP Speed Color FirstGen
Koffing Poison 40 35 Purple True
Milcery Fairy 45 34 White False
Shellder Water 30 40 Purple True
# Selecciona todos los Pokemon amarillos
pframe[pframe['Color'] == 'Yellow']
Name Type HP Speed Color FirstGen
Abra Psychic 25 90 Yellow True
Pikachu Electric 35 90 Yellow True
# Selecciona todos los Pokemon de primera generación con HP mayor a 37
pframe[(pframe['FirstGen'] == True) & (pframe['HP'] > 37)]
Name Type HP Speed Color FirstGen
Koffing Poison 40 35 Purple True
Vulpix Fire 38 65 Red True

Puedes ser tan específico como quieras con esta forma de filtrar. Seleccionar subconjuntos de filas es una habilidad muy útil, así que juega un poco seleccionando basándote en tus propias condiciones.

Bien, creo que estamos bien cuando se trata de seleccionar basándose en etiquetas de columna, ahora seleccionemos filas específicas basándose en el índice. Para esto, Pandas te ofrece dos funciones muy valiosas: loc e iloc.

loc te permite seleccionar basándose en etiquetas de eje, mientras que iloc te permite seleccionar basándose en enteros que representan la posición de la fila. De nuevo es más fácil de entender con ejemplos:

# Selecciona la fila con índice Shellder
pframe.loc['Shellder']
Type         Water
HP              30
Speed           40
Color       Purple
FirstGen      True
Name: Shellder, dtype: object
# Puedes pasar una lista de valores de índice y obtener las filas en el orden especificado
pframe.loc[['Shellder', 'Abra', 'Pikachu']]
Name Type HP Speed Color FirstGen
Shellder Water 30 40 Purple True
Abra Psychic 25 90 Yellow True
Pikachu Electric 35 90 Yellow True
# También es posible obtener solo un subconjunto de columnas usando loc
# Obtengamos datos para Shellder, pero solo el Type y Color
pframe.loc['Shellder', ['Type', 'Color']]
Type      Water
Color    Purple
Name: Shellder, dtype: object
# Si en cambio, necesitas seleccionar elementos basándote en el orden, puedes usar iloc
# Por ejemplo, la siguiente línea selecciona la tercera fila (índice 2, porque 0-indexado)
pframe.iloc[2]
Type        Fairy
HP             45
Speed          34
Color       White
FirstGen    False
Name: Milcery, dtype: object
# Tal como loc, puedes pasar una lista de índices y retornará un dataframe con filas en ese orden
pframe.iloc[[2,4,0]]
Name Type HP Speed Color FirstGen
Milcery Fairy 45 34 White False
Shellder Water 30 40 Purple True
Abra Psychic 25 90 Yellow True
# ¿Recuerdas ese pequeño truco para seleccionar solo un subconjunto de columnas? También funciona para iloc
# Esto selecciona la tercera fila, y solo el Type (columna en posición 0) y HP (columna en posición 1)
pframe.iloc[2, [0, 1]]
Type    Fairy
HP         45
Name: Milcery, dtype: object

Una palabra sobre índices numéricos

loc e iloc son bastante directos, pero es importante entender la diferencia entre ellos. Esto es especialmente cierto cuando se trata de índices numéricos. Un dataframe con índices numéricos que no están en orden, comenzando en 0 y sin interrupción se comportará raro a menos que recuerdes cómo difieren esas funciones. Toma el siguiente dataframe como ejemplo:

frame = pd.DataFrame(np.arange(36).reshape(6,6),
                     columns = ['a', 'b', 'c', 'd', 'e', 'f' ],
                     index = [5, 3, 1, 4, 2, 0])
frame
a b c d e f
5 0 1 2 3 4 5
3 6 7 8 9 10 11
1 12 13 14 15 16 17
4 18 19 20 21 22 23
2 24 25 26 27 28 29
0 30 31 32 33 34 35
# Ahora, revisemos qué retornan loc[2] e iloc[2]
frame.loc[2]
a    24
b    25
c    26
d    27
e    28
f    29
Name: 2, dtype: int64
frame.iloc[2]
a    12
b    13
c    14
d    15
e    16
f    17
Name: 1, dtype: int64

¿Puedes ver que retornan filas diferentes? Esto sucede porque loc[2] busca una fila con un índice con un valor de dos, en este caso, la penúltima fila. Por otro lado, iloc[2] solo busca la tercera fila, la que tiene índice posicional 2, comenzando desde 0. ¡Si recuerdas esto, no tendrás problema lidiando con dataframes con índices numéricos!

La selección es un tema complejo

Una de las grandes cosas sobre Pandas es lo fácil que hace seleccionar solo los datos que necesitas. Como ya sabes, casi toda aplicación avanzada descansa en esta base, ¡y ahora sabes cómo usarla!

Ahora que podemos seleccionar datos y entender cómo funcionan los índices, podemos lidiar con dos temas interesantes: Reindexación y eliminación de entradas.

¡Gracias por leer!

Qué hacer después

Juan Luis Orozco Villalobos

¡Hola! Soy Juan, ingeniero de software y consultor en Budapest. Me especializo en computación en la nube e IA, y me encanta ayudar a otros a aprender sobre tecnología e ingeniería