Tipos de características¶
Definiciones¶
Las características numéricas son números enteros o flotantes que representan una cantidad. También pueden denominarse características cuantitativas.
Las características numéricas deben ser números enteros o flotantes, pero si los tipos de datos indican “objeto”, podría deberse a la presencia de un carácter no numérico como el signo del dólar: $3.00. Asegúrense de abordar estos caracteres y cambiar el tipo de datos a un formato numérico.
Ejemplos:
- Precio
- MPG
- Número de habitaciones
Las características ordinales son categorías que representan diferentes clases y que tienen un ordenamiento distinto.
Pueden ser cadenas o números enteros si estos últimos representan una clase ordenada.
Ejemplos:
- bajo, medio, alto
- Una estrella, dos estrellas, tres estrellas, cuatro estrellas y cinco estrellas
- 0,1,2,3 donde 0 es pequeño, 1 es medio, 2 es grande y 3 es extragrande.
Las características nominales son categorías que representan diferentes clases. No están ordenados.
Pueden ser cadenas o números enteros si estos últimos representan una clase no ordenada.
Ejemplos:
- hombre, mujer, no binario
- rojo, verde, azul, amarillo, púrpura, verde
- 0, 1, 2, 3 donde 0 es soltero, 1 es casado, 2 es divorciado y 3 es viudo
Transformar características¶
Transformar características numéricas¶
Estos ya están en formato numérico, por lo que pueden utilizarse sin más transformación. Sin embargo, es muy común, y a veces necesario, escalar las características numéricas.
¿Por qué estandarización o escalamiento de datos?
El aprendizaje automático es un tema difícil de aprender porque no solo pueden tener errores de programación, sino errores en áreas diferentes. Un error común es el de no comprender los supuestos de un modelo de aprendizaje automático.
Una suposición común en muchos tipos de modelos que los datos están escalados
Definiciones¶
Estandarización: La estandarización es uno de los diversos tipos de escalamiento. Significa el escalamiento de valores para que la distribución tenga una desviación estándar de 1 con una media de 0. El resultado es algo muy parecido a una distribución normal.
StandardScaler: se normaliza restando la media y escalando por su desviación estanda. $$x_{prep} = \dfrac{x-u}{s}$$
La ventaja es que la media del nuevo conjunto de datos cumple con la propiedad que su media $\mu$ es igual a cero y su desviación estandar $s$ es igual a 1.
Escala: Normalmente significa cambiar el rango de los valores. La forma de la distribución no cambia. Piensen que un modo de escala de un edificio tiene las mismas proporciones que el original, pero más pequeñas. Es por eso que decimos que está “dibujado a escala”.
MinMaxScaler: se normaliza ocupando los valores de los mínimos y máximo del conjunto de datos. $$x_{prep} = \dfrac{x-x_{min}}{x_{min}-x_{max}}$$
Esta forma de normalizar resulta útil cuando la desviación estandar $s$ es muy pequeña (cercana) a cero, por lo que lo convierte en un estimador más roubusto que el StandardScaler.
Nota: Los valores escalados pierden sus unidades originales. Los dólares ya no están en unidades de dólar, los metros ya no están en unidades de metro, etc.
Ejemplos¶
En Python se pueden escalar datos usando StandardScaler
de Scikit-learn
.
Para evitar una fuga de datos, el escalador solo debería ajustarse en el conjunto de entrenamiento.
Cuando el escalador se ajusta a los datos, calcula las medias y las desviaciones estándar para cada característica. Luego el escalador se puede usar para transformar los conjuntos de entrenamiento y de prueba basándose en los cálculos que se hicieron en el primer paso. Esto significa que el promedio y la variación (desviación estándar) se calculará usando solo los datos de entrenamiento, ya que queremos mantener información en los datos de prueba, en particular, información sobre las medias y variaciones, que se reservan solo para una evaluación del modelo final.
El escalamiento de los valores objetivos ($y$) no se requiere generalmente.
# librerias
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
# cargar datos
df = pd.read_csv("data/apartments.csv")
df.head()
Sold | SqFt | Price | |
---|---|---|---|
0 | 1 | 200 | 906442 |
1 | 0 | 425 | 272629 |
2 | 1 | 675 | 824862 |
3 | 1 | 984 | 720344 |
4 | 0 | 727 | 879679 |
El objetivo es la columna Sold (vendido) que indica si el departamento se vendió en las 2 semanas siguientes a su publicación. Las características son los metros cuadrados y el precio de lista del apartamento.
# Asignen la columna de objetivo como y
y = df['Sold']
# Asignen el resto de las columnas como X
X = df.drop(columns = 'Sold')
Ahora dividiremos los datos en un conjunto de entrenamiento y conjunto de prueba.
# train/test split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
Antes de hace un escalamiento, exploremos nuestros datos originales. Observen que solo estamos explorando el conjunto de entrenamiento. Mantenemos oculta en nuestro análisis cualquier información sobre el conjunto de prueba.
# Obtengan estadística descriptiva de las características
X_train.describe().round(0)
SqFt | Price | |
---|---|---|
count | 75.0 | 75.0 |
mean | 564.0 | 524950.0 |
std | 285.0 | 274185.0 |
min | 114.0 | 109277.0 |
25% | 320.0 | 272804.0 |
50% | 588.0 | 503613.0 |
75% | 836.0 | 786078.0 |
max | 997.0 | 995878.0 |
La estadística descriptiva de arriba les ayudará a comprender los datos originales (antes que los escalemos). El rengo de SqFt es 114-997 y el de Price es 109277 - 995878. La media de SqFt es 564 y de Price es 524950.
# instancien el escalador
scaler = StandardScaler()
# ajusten el escalador en los datos de entrenamiento
scaler.fit(X_train)
StandardScaler()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
StandardScaler()
El paso de ajuste realiza los cálculos, pero NO los aplica. Después de ajustarlos, los datos siguen siendo los mismos.
Para aplicar los cálculos hechos en el primer paso, hay que transformar los datos. Transformaremos el conjunto de entrenamiento y de prueba.
# transformen los datos de entrenamiento
train_scaled = scaler.transform(X_train)
# transformen los datos de prueba
test_scaled = scaler.transform(X_test)
# observen las 5 primeras filas de train_scaled
train_scaled[:5]
array([[-1.37431725, 1.72912293], [ 1.34901239, -0.33899825], [ 1.35959527, -0.23730597], [ 1.1197165 , -1.01916082], [ 0.98919422, 1.07150845]])
Observen que StandardScaler
, como todos los transformadores sklearn
que vamos a conocer, da salida a arrays de Numpy
, no a DataFrames Pandas. Si queremos convertir un array de NumPy en un DataFrame (que no tenemos que hacerlo necesariamente), podemos usar pd.DataFrame()
.
Vamos a convertir de nuevo a un DataFrame para permitirnos explorar y comprender los efectos de transformar nuestros datos con StandardScaler
# transformen de nuevo a un DataFrame
X_train_scaled = pd.DataFrame(train_scaled, columns=X_train.columns)
X_train_scaled.head()
SqFt | Price | |
---|---|---|
0 | -1.374317 | 1.729123 |
1 | 1.349012 | -0.338998 |
2 | 1.359595 | -0.237306 |
3 | 1.119716 | -1.019161 |
4 | 0.989194 | 1.071508 |
Exploren los datos escalados:
# Obtengan una estadística descriptiva de los datos escalados
# Utilicen .round(2) para eliminar la notación científica y mantener 2 lugares despúes del decimal
X_train_scaled.describe().round(2)
SqFt | Price | |
---|---|---|
count | 75.00 | 75.00 |
mean | -0.00 | 0.00 |
std | 1.01 | 1.01 |
min | -1.59 | -1.53 |
25% | -0.86 | -0.93 |
50% | 0.09 | -0.08 |
75% | 0.96 | 0.96 |
max | 1.53 | 1.73 |
Lo primero que deberían notar sobre la estadística descriptiva es que la media de las características será aproximadamente de 0 y que la desviación estándar será de aproximadamente de 1.
Los datos originales estaban en diferentes escalas. La magnitud del valor ahora representa qué tan lejos está cada valor a partir de la media de cada característica, en unidades de desviación estándar. Los valores que están más cerca de la media estarán más cercanos a cero. A medida que un valor se vuelve notablemente diferente que la media, tendrá una magnitud más grande.
También observarán que algunos valores son negativos y otros positivos. Con la nueva media fijada en 0, cualquier valor por debajo de la media es negativo y cualquier valor por encima de la media es positivo.
Los valores con magnitudes grandes (ya sea en la dirección + o -) se consideran valores atípicos. Si bien no existe un umbral exacto para establecer los valores atípicos, generalmente se consideran atípicos los valores de escala superiores a -3 o 3.
Transformar características ordinales¶
Si son strings, habrá que convertirlas en valores numéricos que representen el orden de las clases.
Observen que a veces esta conversión ya se ha producido, como en el ejemplo anterior, donde 0 es pequeño, 1 es medio, 2 es grande y 3 es extragrande. En este caso, no es necesaria ninguna otra transformación.
Ejemplos de una transformación ordinal de cadena:
- bajo, medio, alto se transformarán en 0, 1, 2
- Una estrella, dos estrellas, tres estrellas, cuatro estrellas, cinco estrellas se transformarán en 0, 1, 2, 3, 4
# ejemplo
import pandas as pd
df =pd.DataFrame({
'Size': ['S','M','M','XL','L','S','L','XL','S'],
'Color':['Blue','Red','Green','Green','Red','Blue','Blue','Red','Green'],
'Cost': [5.00, 7.49, 8.00, 4.00, 9.99, 6.45, 4.32, 8.90, 9.00],
'Sold':['Y','Y','N','N','Y','Y','N','N','Y']
})
df.head()
Size | Color | Cost | Sold | |
---|---|---|---|---|
0 | S | Blue | 5.00 | Y |
1 | M | Red | 7.49 | Y |
2 | M | Green | 8.00 | N |
3 | XL | Green | 4.00 | N |
4 | L | Red | 9.99 | Y |
Reemplacen la característica ordinal (tamaño) con números
Existen varias maneras para lograr esto en Python. Este ejemplo muestra cómo pueden crear un diccionario y utilizar .replace para hacer los cambios. Tengan en cuenta que estamos adquiriendo el hábito de mantener nuestro conjunto de pruebas por separado, pero aplicaremos el mismo preprocesamiento a nuestro conjunto de prueba cuando estemos listos para evaluar nuestro modelo.
# asignen el objetivo y, y las características X
sizes = {'S': 0, 'M': 1, 'L': 2, 'XL': 3}
df['Size'] = df['Size'].replace(sizes)
df.head()
Size | Color | Cost | Sold | |
---|---|---|---|---|
0 | 0 | Blue | 5.00 | Y |
1 | 1 | Red | 7.49 | Y |
2 | 1 | Green | 8.00 | N |
3 | 3 | Green | 4.00 | N |
4 | 2 | Red | 9.99 | Y |
Transformar características nominales¶
Hay que tener cuidado cuando las categorías no están ordenadas. No basta con asignar cada clase a un número, como puede hacerse con las características ordinales.
Esto se debe a que los modelos de aprendizaje automático interpretarán números más altos como si tuvieran un valor más alto que los números más bajos. Sin embargo, no debería haber un valor alto o bajo asociado con variables nominales. Por ejemplo, si solo reemplazaron los valores rojos, verdes, azules con los números 0, 1, 2, el modelo aprendizaje automático interpretará que el azul es mayor que el rojo y el verde. Sabemos que este no debería ser el caso. Todos estos colores se deben tratar como valores iguales ya que ningún color es intrínsecamente mejor/más alto que otro.
Para hacer frente esto, podemos codificar nuestras categorías de una sola vez. Lo que hace esto es crear una columna binaria para cada clase en la columna.
¿Qué es la codificación one-hot?
En primer lugar, la codificación one-hot NO captura el significado de las palabras. La computadora no sabe cómo es el color azul, pero sí puede encontrar relaciones entre el color y otras variables en el contexto de un conjunto de datos. Para representar las características no ordenadas o “nominales”, haremos lo siguiente:
Crear una nueva columna para cada categoría presente en la característica.
Establecer el valor de cada una de las nuevas columnas a 1 si esa fila corresponde a la categoría original
Establecer el valor de cada una de las nuevas columnas a 0 si no lo hacen.
Eliminar la columna original.
La primera fila del DataFrame en la izquiera tiene el valor “rojo” en la columna “color”. En el nuevo DataFrame a la derecha, la primera fila tiene un 1 bajo la columna “color_red” y un 0 en las otras dos columnas. Las categorías desordenadas se han codificado como números.
# ejemplo
# librerias
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.compose import make_column_selector
from sklearn.preprocessing import OneHotEncoder
# leer datos
df = pd.read_csv('data/medical_data.csv')
df.head()
State | Lat | Lng | Area | Children | Age | Income | Marital | Gender | ReAdmis | ... | Hyperlipidemia | BackPain | Anxiety | Allergic_rhinitis | Reflux_esophagitis | Asthma | Services | Initial_days | TotalCharge | Additional_charges | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | AL | 34.34960 | -86.72508 | Suburban | 1.0 | 53 | 86575.93 | Divorced | Male | 0 | ... | 0.0 | 1.0 | 1.0 | 1.0 | 0 | 1 | Blood Work | 10.585770 | 3726.702860 | 17939.403420 |
1 | FL | 30.84513 | -85.22907 | Urban | 3.0 | 51 | 46805.99 | Married | Female | 0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 1 | 0 | Intravenous | 15.129562 | 4193.190458 | 17612.998120 |
2 | SD | 43.54321 | -96.63772 | Suburban | 3.0 | 53 | 14370.14 | Widowed | Female | 0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0 | 0 | Blood Work | 4.772177 | 2434.234222 | 17505.192460 |
3 | MN | 43.89744 | -93.51479 | Suburban | 0.0 | 78 | 39741.49 | Married | Male | 0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 1 | 1 | Blood Work | 1.714879 | 2127.830423 | 12993.437350 |
4 | VA | 37.59894 | -76.88958 | Rural | 1.0 | 22 | 1209.56 | Widowed | Female | 0 | ... | 1.0 | 0.0 | 0.0 | 1.0 | 0 | 0 | CT Scan | 1.254807 | 2113.073274 | 3716.525786 |
5 rows × 32 columns
df.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 1000 entries, 0 to 999 Data columns (total 32 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 State 995 non-null object 1 Lat 1000 non-null float64 2 Lng 1000 non-null float64 3 Area 995 non-null object 4 Children 993 non-null float64 5 Age 1000 non-null int64 6 Income 1000 non-null float64 7 Marital 995 non-null object 8 Gender 995 non-null object 9 ReAdmis 1000 non-null int64 10 VitD_levels 1000 non-null float64 11 Doc_visits 1000 non-null int64 12 Full_meals_eaten 1000 non-null int64 13 vitD_supp 1000 non-null int64 14 Soft_drink 1000 non-null int64 15 Initial_admin 995 non-null object 16 HighBlood 1000 non-null int64 17 Stroke 1000 non-null int64 18 Complication_risk 995 non-null object 19 Overweight 1000 non-null int64 20 Arthritis 994 non-null float64 21 Diabetes 994 non-null float64 22 Hyperlipidemia 998 non-null float64 23 BackPain 992 non-null float64 24 Anxiety 998 non-null float64 25 Allergic_rhinitis 994 non-null float64 26 Reflux_esophagitis 1000 non-null int64 27 Asthma 1000 non-null int64 28 Services 995 non-null object 29 Initial_days 1000 non-null float64 30 TotalCharge 1000 non-null float64 31 Additional_charges 1000 non-null float64 dtypes: float64(14), int64(11), object(7) memory usage: 250.1+ KB
Hay numerosas columnas de “objeto” que tendrán que ser codificadas.
La columna Complication_Risk
está ordenada, y podemos usar codificación ordinal para esta. El método df.replace()
funciona para esto.
df['Complication_risk'].value_counts()
Medium 459 High 311 Low 221 Med 4 Name: Complication_risk, dtype: int64
df['Complication_risk'].replace({'Low':0, 'Med':1, 'Medium':1, 'High':2}, inplace=True)
df['Complication_risk'].value_counts()
1.0 463 2.0 311 0.0 221 Name: Complication_risk, dtype: int64
Nota: La codificación ordinal que hicimos arriba no dependió de la información de los datos de prueba, por lo que no causaría una fuga de datos. Podemos hacer esto antes de dividir los datos.
Para esta tarea, el propósito es predecir los Additional charges (gastos adicionales) que se basan en las otras características en el conjunto de datos.
Asignaremos Additional_charges como nuestro objetivo (y).
Asignaremos el resto de las columnas como las características (X). También eliminaremos la columna "Unnamed: 0", ya que no es una característica relevante.
X = df.drop(columns = ['Additional_charges'])
y = df['Additional_charges']
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=42)
Solo queremos una codificación one-hot para las características categóricas, NO para las características numéricas, por lo que necesitamos una manera de dividir las características categóricas de las numéricas. Podríamos hacer esto manualmente, pero make_column_selector
nos permitirá hacer esto más eficazmente.
En este caso le diremos a make_column_selector que solo seleccione las columnas con el tipo object
.
# hagan un selector categórico
cat_selector = make_column_selector(dtype_include='object')
Cuando aplicamos el cat_selector aun DataFrame, volverá a una lista con los nombres de las columnas que coinciden con el patrón que le dimos.
cat_selector(X_train)
['State', 'Area', 'Marital', 'Gender', 'Initial_admin', 'Services']
Ahora podemos utilizar esa lista a un subconjunto de un conjunto de datos original.
El código de abajo crea dos DataFrames nuevos (train_cat_data and test_cat_data) que contiene solo seleccionado las características del objeto con cat_selector
.
# creen un subconjunto de datos solo para las columnas categóricas
train_cat_data = X_train[cat_selector(X_train)]
test_cat_data = X_test[cat_selector(X_test)]
train_cat_data.head()
State | Area | Marital | Gender | Initial_admin | Services | |
---|---|---|---|---|---|---|
82 | TN | Urban | Never Married | Female | Emergency Admission | Intravenous |
991 | AL | Urban | Married | Male | Emergency Admission | Blood Work |
789 | TN | Urban | Married | Nonbinary | Observation Admission | Intravenous |
894 | SD | Rural | Never Married | Male | Observation Admission | Blood Work |
398 | MI | Suburban | Widowed | Female | Elective Admission | Blood Work |
Estamos listos para la codificación one-hot en las características categóricas
# instancien la codificación one-hot
ohe_encoder = OneHotEncoder(sparse_output=False, handle_unknown='ignore')
# ajusten el OneHotEncoder en los datos de entrenamiento
ohe_encoder.fit(train_cat_data)
# transforme los datos de entrenamiento y de prueba
train_ohe = ohe_encoder.transform(train_cat_data)
test_ohe = ohe_encoder.transform(test_cat_data)
train_ohe
array([[0., 0., 0., ..., 1., 0., 0.], [0., 1., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 1., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]])
Observen que la salida de un array de NumPy en lugar de un DataFrame.
Podemos usar el método get_feature_names_out()
para obtener una lista de las nuevas características, pero debemos pasarlas a la lista de columnas originales (de antes de la codificación de los datos).
# conviertan a un DataFrame, obtengan una nueva columna de nombres a partir de la codificación
# establezcan prefijos a la columna de nombres original
ohe_column_names = ohe_encoder.get_feature_names_out(train_cat_data.columns)
train_ohe = pd.DataFrame(train_ohe, columns=ohe_column_names)
test_ohe = pd.DataFrame(test_ohe, columns=ohe_column_names)
train_ohe.head()
State_AK | State_AL | State_AR | State_AZ | State_CA | State_CO | State_CT | State_DC | State_FL | State_GA | ... | Gender_nan | Initial_admin_Elective Admission | Initial_admin_Emergency Admission | Initial_admin_Observation Admission | Initial_admin_nan | Services_Blood Work | Services_CT Scan | Services_Intravenous | Services_MRI | Services_nan | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
1 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
3 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | ... | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
5 rows × 78 columns
Observen que habrá un “0,0” para todas las columnas de “state” de cada fila, excepto una. La columna que corresponde a “state” para esa fila tendrá un “1,0”.
Concatenar las características categóricas de codificación one-hot con las numéricas
Podemos usar la función de Pandas: pd.concat()
para alcanzar esto. La función pd.concat()
toma una lista de los DataFrames para concatenarlos juntos. Por defecto los concatena en el eje 0, las filas.
Nota: También hay que resaltar que Pandas intentará usar el índice para determinar cómo igualar las filas. Cuando dividimos los datos, se mezclan con el índice, y cuando hace una codificación one-hot en los datos, restablecen el índice.
# creen un selector numérico
num_selector = make_column_selector(dtype_include='number')
# aislen las columnas numéricas
train_nums = X_train[num_selector(X_train)].reset_index(drop=True)
test_nums = X_test[num_selector(X_test)].reset_index(drop=True)
# recombinen los conjuntos de entrenamiento y de prueba en el eje 1 (columnas)
X_train_processed = pd.concat([train_nums, train_ohe], axis=1)
X_test_processed = pd.concat([test_nums, test_ohe], axis=1)
X_train_processed.head()
Lat | Lng | Children | Age | Income | ReAdmis | VitD_levels | Doc_visits | Full_meals_eaten | vitD_supp | ... | Gender_nan | Initial_admin_Elective Admission | Initial_admin_Emergency Admission | Initial_admin_Observation Admission | Initial_admin_nan | Services_Blood Work | Services_CT Scan | Services_Intravenous | Services_MRI | Services_nan | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 36.16307 | -86.66510 | 2.0 | 60 | 8459.99 | 0 | 19.034162 | 5 | 1 | 0 | ... | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
1 | 34.96594 | -87.12179 | 5.0 | 78 | 22669.31 | 0 | 15.903388 | 7 | 1 | 0 | ... | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 36.24648 | -83.51232 | 1.0 | 60 | 25536.25 | 0 | 18.225040 | 4 | 1 | 0 | ... | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
3 | 45.42189 | -97.91165 | 7.0 | 82 | 94863.57 | 0 | 15.809932 | 5 | 0 | 2 | ... | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 42.33661 | -83.28292 | 0.0 | 37 | 30898.36 | 0 | 20.640410 | 5 | 1 | 0 | ... | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 | 0.0 | 0.0 |
5 rows × 103 columns
Todas las columnas en nuestro DataFrame son ahora numéricas sin pérdida de datos. Este DataFrame se puede usar en un modelo, sin embargo, es probable que también queramos escalar las columnas numéricas si estamos usando ciertos tipos de modelos.
¿Por qué no podemos hacer una codificación one-hot en los datos antes de dividirlos?
A veces solo hay unas pocas, incluso a veces una, muestras con una categoría en particular en una característica. Cuando dividimos los datos, esa muestra podría posiblemente terminar en el conjunto de prueba. Esto sería análogo a un modelo de producción desplegado que se encuentra con una categoría que nunca había visto antes. ¿Debería una columna existir antes para esa categoría? No tenemos manera de saber (en teoría) como serían esas categorías ocultas, por lo que no podemos crear columnas nuevas para ellas.