Una variable categórica solo puede tener un número limitado, y generalmente fijo, de valores posibles (categorías). Algunos ejemplos de variables de este tipo pueden ser el género y el tipo de sangre.
Pueden tener un orden (por ejemplo, ‘muy de acuerdo’ podría ir primero y ‘muy en desacuerdo’ podría ir en último lugar), pero las operaciones numéricas (sumas, restas, divisiones, …) no son posibles.
Convertir una columna en variable categórica
Convertir variable discreta
python
df = pd.read_csv("C:/Users/user/Desktop/adult-stretch.data", header=None, names = ["Color", "Size", "Other_column", "Age", "Target"])
df
| Color | Size | Other_column | Age | Target |
|---|
| 0 | YELLOW | SMALL | STRETCH | ADULT | T |
|---|
| 1 | YELLOW | SMALL | STRETCH | CHILD | T |
|---|
| 2 | YELLOW | SMALL | DIP | ADULT | T |
|---|
| 3 | YELLOW | SMALL | DIP | CHILD | F |
|---|
| 4 | YELLOW | SMALL | DIP | CHILD | F |
|---|
| 5 | YELLOW | LARGE | STRETCH | ADULT | T |
|---|
| 6 | YELLOW | LARGE | STRETCH | CHILD | T |
|---|
| 7 | YELLOW | LARGE | DIP | ADULT | T |
|---|
| 8 | YELLOW | LARGE | DIP | CHILD | F |
|---|
| 9 | YELLOW | LARGE | DIP | CHILD | F |
|---|
| 10 | PURPLE | SMALL | STRETCH | ADULT | T |
|---|
| 11 | PURPLE | SMALL | STRETCH | CHILD | T |
|---|
| 12 | PURPLE | SMALL | DIP | ADULT | T |
|---|
| 13 | PURPLE | SMALL | DIP | CHILD | F |
|---|
| 14 | PURPLE | SMALL | DIP | CHILD | F |
|---|
| 15 | PURPLE | LARGE | STRETCH | ADULT | T |
|---|
| 16 | PURPLE | LARGE | STRETCH | CHILD | T |
|---|
| 17 | PURPLE | LARGE | DIP | ADULT | T |
|---|
| 18 | PURPLE | LARGE | DIP | CHILD | F |
|---|
| 19 | PURPLE | LARGE | DIP | CHILD | F |
|---|
python
Index(['Color', 'Size', 'Other_column', 'Age', 'Target'], dtype='object')
python
Color object
Size object
Other_column object
Age object
Target object
dtype: object
python
df["Color"] = df["Color"].astype("category")
df.dtypes
Color category
Size object
Other_column object
Age object
Target object
dtype: object
Convertir variable continua
python
df2 = pd.DataFrame({"Edad": np.random.randint(0, 100, 20)})
df2
| Edad |
|---|
| 0 | 94 |
|---|
| 1 | 40 |
|---|
| 2 | 53 |
|---|
| 3 | 34 |
|---|
| 4 | 62 |
|---|
| 5 | 38 |
|---|
| 6 | 61 |
|---|
| 7 | 90 |
|---|
| 8 | 35 |
|---|
| 9 | 75 |
|---|
| 10 | 64 |
|---|
| 11 | 78 |
|---|
| 12 | 43 |
|---|
| 13 | 73 |
|---|
| 14 | 87 |
|---|
| 15 | 60 |
|---|
| 16 | 54 |
|---|
| 17 | 24 |
|---|
| 18 | 26 |
|---|
| 19 | 68 |
|---|
python
labels = ["{0} - {1}".format(i, i+9) for i in range(0,100,10)]
labels
['0 - 9',
'10 - 19',
'20 - 29',
'30 - 39',
'40 - 49',
'50 - 59',
'60 - 69',
'70 - 79',
'80 - 89',
'90 - 99']
python
df2["Grupo_edad"] = pd.cut(df2.Edad, range(0,105,10), right = False, labels = labels)
df2
| Edad | Grupo_edad |
|---|
| 0 | 94 | 90 - 99 |
|---|
| 1 | 40 | 40 - 49 |
|---|
| 2 | 53 | 50 - 59 |
|---|
| 3 | 34 | 30 - 39 |
|---|
| 4 | 62 | 60 - 69 |
|---|
| 5 | 38 | 30 - 39 |
|---|
| 6 | 61 | 60 - 69 |
|---|
| 7 | 90 | 90 - 99 |
|---|
| 8 | 35 | 30 - 39 |
|---|
| 9 | 75 | 70 - 79 |
|---|
| 10 | 64 | 60 - 69 |
|---|
| 11 | 78 | 70 - 79 |
|---|
| 12 | 43 | 40 - 49 |
|---|
| 13 | 73 | 70 - 79 |
|---|
| 14 | 87 | 80 - 89 |
|---|
| 15 | 60 | 60 - 69 |
|---|
| 16 | 54 | 50 - 59 |
|---|
| 17 | 24 | 20 - 29 |
|---|
| 18 | 26 | 20 - 29 |
|---|
| 19 | 68 | 60 - 69 |
|---|
Renombrar categorías
python
['YELLOW', 'PURPLE']
Categories (2, object): ['YELLOW', 'PURPLE']
python
df.Color.cat.rename_categories({"YELLOW": "AMARILLO", "PURPLE": "MORADO"}, inplace=True)
python
| Color | Size | Other_column | Age | Target |
|---|
| 0 | AMARILLO | SMALL | STRETCH | ADULT | T |
|---|
| 1 | AMARILLO | SMALL | STRETCH | CHILD | T |
|---|
| 2 | AMARILLO | SMALL | DIP | ADULT | T |
|---|
| 3 | AMARILLO | SMALL | DIP | CHILD | F |
|---|
| 4 | AMARILLO | SMALL | DIP | CHILD | F |
|---|
| 5 | AMARILLO | LARGE | STRETCH | ADULT | T |
|---|
| 6 | AMARILLO | LARGE | STRETCH | CHILD | T |
|---|
| 7 | AMARILLO | LARGE | DIP | ADULT | T |
|---|
| 8 | AMARILLO | LARGE | DIP | CHILD | F |
|---|
| 9 | AMARILLO | LARGE | DIP | CHILD | F |
|---|
| 10 | MORADO | SMALL | STRETCH | ADULT | T |
|---|
| 11 | MORADO | SMALL | STRETCH | CHILD | T |
|---|
| 12 | MORADO | SMALL | DIP | ADULT | T |
|---|
| 13 | MORADO | SMALL | DIP | CHILD | F |
|---|
| 14 | MORADO | SMALL | DIP | CHILD | F |
|---|
| 15 | MORADO | LARGE | STRETCH | ADULT | T |
|---|
| 16 | MORADO | LARGE | STRETCH | CHILD | T |
|---|
| 17 | MORADO | LARGE | DIP | ADULT | T |
|---|
| 18 | MORADO | LARGE | DIP | CHILD | F |
|---|
| 19 | MORADO | LARGE | DIP | CHILD | F |
|---|
Añadir categorías
python
df.Color.cat.add_categories("AZUL")
0 AMARILLO
1 AMARILLO
2 AMARILLO
3 AMARILLO
4 AMARILLO
5 AMARILLO
6 AMARILLO
7 AMARILLO
8 AMARILLO
9 AMARILLO
10 MORADO
11 MORADO
12 MORADO
13 MORADO
14 MORADO
15 MORADO
16 MORADO
17 MORADO
18 MORADO
19 MORADO
Name: Color, dtype: category
Categories (3, object): ['MORADO', 'AMARILLO', 'AZUL']
Eliminar categorías
python
df.Color.cat.remove_unused_categories()
0 AMARILLO
1 AMARILLO
2 AMARILLO
3 AMARILLO
4 AMARILLO
5 AMARILLO
6 AMARILLO
7 AMARILLO
8 AMARILLO
9 AMARILLO
10 MORADO
11 MORADO
12 MORADO
13 MORADO
14 MORADO
15 MORADO
16 MORADO
17 MORADO
18 MORADO
19 MORADO
Name: Color, dtype: category
Categories (2, object): ['MORADO', 'AMARILLO']
Ordenar por categoría
python
df.sort_values(by="Color", ascending=True)
| Color | Size | Other_column | Age | Target |
|---|
| 19 | MORADO | LARGE | DIP | CHILD | F |
|---|
| 17 | MORADO | LARGE | DIP | ADULT | T |
|---|
| 16 | MORADO | LARGE | STRETCH | CHILD | T |
|---|
| 15 | MORADO | LARGE | STRETCH | ADULT | T |
|---|
| 14 | MORADO | SMALL | DIP | CHILD | F |
|---|
| 13 | MORADO | SMALL | DIP | CHILD | F |
|---|
| 12 | MORADO | SMALL | DIP | ADULT | T |
|---|
| 11 | MORADO | SMALL | STRETCH | CHILD | T |
|---|
| 10 | MORADO | SMALL | STRETCH | ADULT | T |
|---|
| 18 | MORADO | LARGE | DIP | CHILD | F |
|---|
| 0 | AMARILLO | SMALL | STRETCH | ADULT | T |
|---|
| 7 | AMARILLO | LARGE | DIP | ADULT | T |
|---|
| 6 | AMARILLO | LARGE | STRETCH | CHILD | T |
|---|
| 5 | AMARILLO | LARGE | STRETCH | ADULT | T |
|---|
| 4 | AMARILLO | SMALL | DIP | CHILD | F |
|---|
| 3 | AMARILLO | SMALL | DIP | CHILD | F |
|---|
| 2 | AMARILLO | SMALL | DIP | ADULT | T |
|---|
| 1 | AMARILLO | SMALL | STRETCH | CHILD | T |
|---|
| 8 | AMARILLO | LARGE | DIP | CHILD | F |
|---|
| 9 | AMARILLO | LARGE | DIP | CHILD | F |
|---|
python
Edad int64
Grupo_edad category
dtype: object
python
df2.sort_values(by="Grupo_edad", ascending=True)
| Edad | Grupo_edad |
|---|
| 17 | 24 | 20 - 29 |
|---|
| 18 | 26 | 20 - 29 |
|---|
| 3 | 34 | 30 - 39 |
|---|
| 5 | 38 | 30 - 39 |
|---|
| 8 | 35 | 30 - 39 |
|---|
| 1 | 40 | 40 - 49 |
|---|
| 12 | 43 | 40 - 49 |
|---|
| 2 | 53 | 50 - 59 |
|---|
| 16 | 54 | 50 - 59 |
|---|
| 19 | 68 | 60 - 69 |
|---|
| 4 | 62 | 60 - 69 |
|---|
| 6 | 61 | 60 - 69 |
|---|
| 10 | 64 | 60 - 69 |
|---|
| 15 | 60 | 60 - 69 |
|---|
| 9 | 75 | 70 - 79 |
|---|
| 13 | 73 | 70 - 79 |
|---|
| 11 | 78 | 70 - 79 |
|---|
| 14 | 87 | 80 - 89 |
|---|
| 7 | 90 | 90 - 99 |
|---|
| 0 | 94 | 90 - 99 |
|---|
Agrupar por categoría
python
df2.groupby("Grupo_edad").size()
Grupo_edad
0 - 9 0
10 - 19 0
20 - 29 2
30 - 39 3
40 - 49 2
50 - 59 2
60 - 69 5
70 - 79 3
80 - 89 1
90 - 99 2
dtype: int64
Tratamiento de variables categóricas
Eliminar variables categóricas
La manera más simple de atajar el problema de las variables categóricas consiste en eliminarlas del conjunto de datos. Sin embargo, este enfoque puede provocar una pérdida de información potencialmente valiosa para el modelo de Machine Learning.
Método de label encoding
El método de label encoding (o codificación de etiqueta) consiste en asignar un número entero a cada valor diferente de una variable. El problema de este enfoque es que implica asumir un orden en las categorías, y las variables categóricas no siempre llevan implícito un orden claro. Por tanto, esta técnica es apropiada cuando se están tratando variables ordinales.
python
| Color | Size | Other_column | Age | Target |
|---|
| 0 | YELLOW | SMALL | STRETCH | ADULT | T |
|---|
| 1 | YELLOW | SMALL | STRETCH | CHILD | T |
|---|
| 2 | YELLOW | SMALL | DIP | ADULT | T |
|---|
| 3 | YELLOW | SMALL | DIP | CHILD | F |
|---|
| 4 | YELLOW | SMALL | DIP | CHILD | F |
|---|
| 5 | YELLOW | LARGE | STRETCH | ADULT | T |
|---|
| 6 | YELLOW | LARGE | STRETCH | CHILD | T |
|---|
| 7 | YELLOW | LARGE | DIP | ADULT | T |
|---|
| 8 | YELLOW | LARGE | DIP | CHILD | F |
|---|
| 9 | YELLOW | LARGE | DIP | CHILD | F |
|---|
| 10 | PURPLE | SMALL | STRETCH | ADULT | T |
|---|
| 11 | PURPLE | SMALL | STRETCH | CHILD | T |
|---|
| 12 | PURPLE | SMALL | DIP | ADULT | T |
|---|
| 13 | PURPLE | SMALL | DIP | CHILD | F |
|---|
| 14 | PURPLE | SMALL | DIP | CHILD | F |
|---|
| 15 | PURPLE | LARGE | STRETCH | ADULT | T |
|---|
| 16 | PURPLE | LARGE | STRETCH | CHILD | T |
|---|
| 17 | PURPLE | LARGE | DIP | ADULT | T |
|---|
| 18 | PURPLE | LARGE | DIP | CHILD | F |
|---|
| 19 | PURPLE | LARGE | DIP | CHILD | F |
|---|
python
color_map = {"YELLOW": 1, "PURPLE": 2}
df["Color_numeric"] = df.Color.map(color_map)
df
| Color | Size | Other_column | Age | Target | Color_numeric |
|---|
| 0 | YELLOW | SMALL | STRETCH | ADULT | T | 1 |
|---|
| 1 | YELLOW | SMALL | STRETCH | CHILD | T | 1 |
|---|
| 2 | YELLOW | SMALL | DIP | ADULT | T | 1 |
|---|
| 3 | YELLOW | SMALL | DIP | CHILD | F | 1 |
|---|
| 4 | YELLOW | SMALL | DIP | CHILD | F | 1 |
|---|
| 5 | YELLOW | LARGE | STRETCH | ADULT | T | 1 |
|---|
| 6 | YELLOW | LARGE | STRETCH | CHILD | T | 1 |
|---|
| 7 | YELLOW | LARGE | DIP | ADULT | T | 1 |
|---|
| 8 | YELLOW | LARGE | DIP | CHILD | F | 1 |
|---|
| 9 | YELLOW | LARGE | DIP | CHILD | F | 1 |
|---|
| 10 | PURPLE | SMALL | STRETCH | ADULT | T | 2 |
|---|
| 11 | PURPLE | SMALL | STRETCH | CHILD | T | 2 |
|---|
| 12 | PURPLE | SMALL | DIP | ADULT | T | 2 |
|---|
| 13 | PURPLE | SMALL | DIP | CHILD | F | 2 |
|---|
| 14 | PURPLE | SMALL | DIP | CHILD | F | 2 |
|---|
| 15 | PURPLE | LARGE | STRETCH | ADULT | T | 2 |
|---|
| 16 | PURPLE | LARGE | STRETCH | CHILD | T | 2 |
|---|
| 17 | PURPLE | LARGE | DIP | ADULT | T | 2 |
|---|
| 18 | PURPLE | LARGE | DIP | CHILD | F | 2 |
|---|
| 19 | PURPLE | LARGE | DIP | CHILD | F | 2 |
|---|
python
Color category
Size object
Other_column object
Age object
Target object
Color_numeric category
dtype: object
python
0 1
1 1
2 1
3 1
4 1
5 1
6 1
7 1
8 1
9 1
10 0
11 0
12 0
13 0
14 0
15 0
16 0
17 0
18 0
19 0
dtype: int8
python
df["Color_codes"] = df.Color.cat.codes
df
| Color | Size | Other_column | Age | Target | Color_numeric | Color_codes |
|---|
| 0 | YELLOW | SMALL | STRETCH | ADULT | T | 1 | 1 |
|---|
| 1 | YELLOW | SMALL | STRETCH | CHILD | T | 1 | 1 |
|---|
| 2 | YELLOW | SMALL | DIP | ADULT | T | 1 | 1 |
|---|
| 3 | YELLOW | SMALL | DIP | CHILD | F | 1 | 1 |
|---|
| 4 | YELLOW | SMALL | DIP | CHILD | F | 1 | 1 |
|---|
| 5 | YELLOW | LARGE | STRETCH | ADULT | T | 1 | 1 |
|---|
| 6 | YELLOW | LARGE | STRETCH | CHILD | T | 1 | 1 |
|---|
| 7 | YELLOW | LARGE | DIP | ADULT | T | 1 | 1 |
|---|
| 8 | YELLOW | LARGE | DIP | CHILD | F | 1 | 1 |
|---|
| 9 | YELLOW | LARGE | DIP | CHILD | F | 1 | 1 |
|---|
| 10 | PURPLE | SMALL | STRETCH | ADULT | T | 2 | 0 |
|---|
| 11 | PURPLE | SMALL | STRETCH | CHILD | T | 2 | 0 |
|---|
| 12 | PURPLE | SMALL | DIP | ADULT | T | 2 | 0 |
|---|
| 13 | PURPLE | SMALL | DIP | CHILD | F | 2 | 0 |
|---|
| 14 | PURPLE | SMALL | DIP | CHILD | F | 2 | 0 |
|---|
| 15 | PURPLE | LARGE | STRETCH | ADULT | T | 2 | 0 |
|---|
| 16 | PURPLE | LARGE | STRETCH | CHILD | T | 2 | 0 |
|---|
| 17 | PURPLE | LARGE | DIP | ADULT | T | 2 | 0 |
|---|
| 18 | PURPLE | LARGE | DIP | CHILD | F | 2 | 0 |
|---|
| 19 | PURPLE | LARGE | DIP | CHILD | F | 2 | 0 |
|---|
Método de one-hot encoding
El método de one-hot encoding (o codificación one-hot) consiste en crear nuevas columnas indicando la presencia o ausencia de cada posible valor de una variable categórica.
One-hot encoding, al contrario que el método de label encoding, no implica asumir un orden en las categorías. Por tanto, esta técnica es apropiada para tratar variables nominales. Sin embargo, es importante tener en cuenta que el método de one-hot encoding no suele dar buenos resultados si hay muchos valores diferentes para la variable categórica que se está procesando (generalmente, más de 15).
python
pd.get_dummies(data=df, columns=["Color"], drop_first=True)
| Size | Other_column | Age | Target | Color_numeric | Color_codes | Color_YELLOW |
|---|
| 0 | SMALL | STRETCH | ADULT | T | 1 | 1 | 1 |
|---|
| 1 | SMALL | STRETCH | CHILD | T | 1 | 1 | 1 |
|---|
| 2 | SMALL | DIP | ADULT | T | 1 | 1 | 1 |
|---|
| 3 | SMALL | DIP | CHILD | F | 1 | 1 | 1 |
|---|
| 4 | SMALL | DIP | CHILD | F | 1 | 1 | 1 |
|---|
| 5 | LARGE | STRETCH | ADULT | T | 1 | 1 | 1 |
|---|
| 6 | LARGE | STRETCH | CHILD | T | 1 | 1 | 1 |
|---|
| 7 | LARGE | DIP | ADULT | T | 1 | 1 | 1 |
|---|
| 8 | LARGE | DIP | CHILD | F | 1 | 1 | 1 |
|---|
| 9 | LARGE | DIP | CHILD | F | 1 | 1 | 1 |
|---|
| 10 | SMALL | STRETCH | ADULT | T | 2 | 0 | 0 |
|---|
| 11 | SMALL | STRETCH | CHILD | T | 2 | 0 | 0 |
|---|
| 12 | SMALL | DIP | ADULT | T | 2 | 0 | 0 |
|---|
| 13 | SMALL | DIP | CHILD | F | 2 | 0 | 0 |
|---|
| 14 | SMALL | DIP | CHILD | F | 2 | 0 | 0 |
|---|
| 15 | LARGE | STRETCH | ADULT | T | 2 | 0 | 0 |
|---|
| 16 | LARGE | STRETCH | CHILD | T | 2 | 0 | 0 |
|---|
| 17 | LARGE | DIP | ADULT | T | 2 | 0 | 0 |
|---|
| 18 | LARGE | DIP | CHILD | F | 2 | 0 | 0 |
|---|
| 19 | LARGE | DIP | CHILD | F | 2 | 0 | 0 |
|---|
python
Color category
Size object
Other_column object
Age object
Target object
Color_numeric category
Color_codes int8
dtype: object
python
| Color_codes | Color_PURPLE | Color_YELLOW | Size_LARGE | Size_SMALL | Other_column_DIP | Other_column_STRETCH | Age_ADULT | Age_CHILD | Target_F | Target_T | Color_numeric_2 | Color_numeric_1 |
|---|
| 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
|---|
| 1 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
|---|
| 2 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
|---|
| 3 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
|---|
| 4 | 1 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
|---|
| 5 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 |
|---|
| 6 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 |
|---|
| 7 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 |
|---|
| 8 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
|---|
| 9 | 1 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 |
|---|
| 10 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
|---|
| 11 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 |
|---|
| 12 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
|---|
| 13 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
|---|
| 14 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
|---|
| 15 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 |
|---|
| 16 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 0 |
|---|
| 17 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 |
|---|
| 18 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
|---|
| 19 | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 |
|---|