Python

Segmentar datos numéricos en Pandas con la función cut()

Al trabajar con datos numéricos, para facilitar su análisis e interpretación, puede ser necesario agrupar estos en intervalos de valores discretos. Lo que permite convertir datos numéricos en categorías o clases. La función cut permite segmentar datos numéricos en Pandas de una manera sencilla.

Descripción de la función cut() de Pandas

La función cut() de Pandas permite dividir los valores numéricos de la series de datos en contenedores o bins, donde cada uno de estos bins representa un intervalo de valores. Lo que permite categorizar los datos de una forma significativa. Algo que es especialmente útil durante las fases de análisis y visualización de los datos, ya que permite representar la información de una manera más clara.

Uso básico de la función cut() de Pandas

La función cut() de Pandas requiere que se le indiquen dos parámetros para poder funcionar: los valores que se desea segmentar y los límites de los contenedores o bins. En ambos casos se pueden usar cualquier elemento que represente una serie de listas.

A modo de ejemplo, para ver el funcionamiento de esta función se puede usar el conjunto de datos planets de Seaborn que contiene diferentes características de exoplanetas (un conjunto que ya se ha usado para explicar cómo ordenar valores o crear gráficos de correlación). Como puede ser la columna mass que incluye la masa de los exoplanetas. Si se desea segmentar los registros en base a la masa solamente se tiene que definir un rango de valores y llamar a la función cut() para que realice la tarea. Esto es lo que se hace en el siguiente ejemplo.

import seaborn as sns
import pandas as pd

# Cargar el dataset "planets" de Seaborn
planets_data = sns.load_dataset("planets")

# Definición de las categorias de masa
mass_bins = [0, 2, 5, 10, 50]

# Uso de la función cut para segmentar los planetas por masa
mass = pd.cut(planets_data['mass'], mass_bins)

print(mass)
0        (5.0, 10.0]
1         (2.0, 5.0]
2         (2.0, 5.0]
3       (10.0, 50.0]
4       (10.0, 50.0]
            ...     
1030             NaN
1031             NaN
1032             NaN
1033             NaN
1034             NaN
Name: mass, Length: 1035, dtype: category
Categories (4, interval[int64, right]): [(0, 2] < (2, 5] < (5, 10] < (10, 50]]

En donde en primer lugar se importan las librerías y se carga el conjunto de datos. Posteriormente se define mediante una lista los rangos de categorías para la masa, se llama a la función cut() para segmentar los datos y, finalmente, se muestra el resultado. En dónde se puede ver una serie en la que a cada uno de los registros se le asigna un rango ((0, 2], (2, 5], (5, 10], (10, 50]) o NaN cuando los valores no caen dentro los rangos definidos o son son nulos.

Por defecto los rangos incluyen los valores por la derecha y no por la izquierda. Esto es, el rango (2, 5] incluye los planetas con masa mayor de 2, pero no 2, hasta 5 incluido. Un comportamiento que se puede cambiar asignado el valor falso a la propiedad right para que se incluyan los valores por la izquierda.

Ahora se puede usar la función value_counts() de Pandas para contabilizar el número de registros en cada uno de los segmentos.

pd.value_counts(mass)
(0, 2]      333
(2, 5]       95
(5, 10]      55
(10, 50]     30
Name: mass, dtype: int64

Personalización de las etiquetas

Usar directamente los valores de los rangos puede ser algo poco intuitivo, por lo que se le pueden asignar etiquetas personalizadas cuando se realiza la segmentación. Para lo que la función cut() dispone de la propiedad labels. Por ejemplo, los grupos de planetas se puede vivir en tierras, supertierras, minineptunos y neptunianos. Lo que se muestra en el siguiente ejemplo.

# Usar la función cut con etiquetas personalizadas
mass = pd.cut(planets_data['mass'], mass_bins,
              labels=['Tierras', 'Supertierras', 'Minineptunos', 'Neptunianos'])

print(mass)
print()
print(pd.value_counts(mass))
0       Minineptunos
1       Supertierras
2       Supertierras
3        Neptunianos
4        Neptunianos
            ...     
1030             NaN
1031             NaN
1032             NaN
1033             NaN
1034             NaN
Name: mass, Length: 1035, dtype: category
Categories (4, object): ['Tierras' < 'Supertierras' < 'Minineptunos' < 'Neptunianos']

Tierras         333
Supertierras     95
Minineptunos     55
Neptunianos      30
Name: mass, dtype: int64

Ahora el resultado es más intuitivo, pero no se cuentan los planetas con masa desconocida. Para ello se puede asignar una categoría nueva y reemplazar los valores nulos por esta. Algo que se puede conseguir con el siguiente código.

mass = mass.cat.add_categories('Desconocido').fillna('Desconocido')

print(mass)
print()
print(pd.value_counts(mass))
0       Minineptunos
1       Supertierras
2       Supertierras
3        Neptunianos
4        Neptunianos
            ...     
1030     Desconocido
1031     Desconocido
1032     Desconocido
1033     Desconocido
1034     Desconocido
Name: mass, Length: 1035, dtype: category
Categories (5, object): ['Tierras' < 'Supertierras' < 'Minineptunos' < 'Neptunianos' < 'Desconocido']

Desconocido     522
Tierras         333
Supertierras     95
Minineptunos     55
Neptunianos      30
Name: mass, dtype: int64

Haciendo aún más sencilla la interpretación de los datos. Poniendo de manifiesto que la mayoría de los registros de este conjunto de datos no se conoce la masa de los planetas.

Es importante definir la categoría antes de reemplazar los valores nulos por ésta, en caso contrario se producirá un error porque la categoría no existe en la lista de posibles opciones. Por eso en el ejemplo se ha agregado la categoría mediante el método add_categories().

Conclusiones

La función cut() es una herramienta con la que se puede segmentar datos numéricos en Pandas de una manera rápida y sencilla. Permitiendo análisis y visualizaciones de datos más intuitivos. Así, el uso de esta función ayuda a obtener una mejor comprensión de los conjuntos de datos durante el trabajo diario.

Image by NoName_13 from Pixabay

¿Te ha parecido de utilidad el contenido?

Daniel Rodríguez

Share
Published by
Daniel Rodríguez
Tags: Pandas

Recent Posts

Por Qué las Contraseñas Largas son más Seguras que las Complejas

"Tu contraseña debe tener al menos 8 caracteres, una mayúscula, un número y un símbolo…

5 días ago

Gini, KS y AUC: Cómo Medir la Calidad de un Modelo de Credit Scoring

Cuando un analista de riesgo presenta un nuevo scorecard ante el comité de dirección, la…

7 días ago

Curiosidad: De dónde vienen foo, bar y foobar

Si revisáis código o documentación de otros programadores, tarde o temprano os toparéis con dos…

2 semanas ago

BG/NBD + Gamma/Gamma: el modelo probabilístico para CLV en compras continuas

Los dos artículos anteriores cubrieron el CLV clásico —una fórmula útil pero que trata a…

2 semanas ago

Errores habituales al trabajar con DataFrames grandes en Pandas (y cómo evitarlos)

Hay un momento muy concreto en la vida de casi todo análisis: el código que…

3 semanas ago

Champion vs Challenger: Cómo los Bancos Validan Modelos Nuevos antes de Ponerlos en Producción

Has construido un nuevo modelo de credit scoring. Las métricas de validación son mejores que…

3 semanas ago

This website uses cookies.