Normalizar columnas de un marco de datos
Tengo un marco de datos en pandas donde cada columna tiene un rango de valores diferente. Por ejemplo:
df:
A B C
1000 10 0.5
765 5 0.35
800 7 0.09
¿Alguna idea de cómo puedo normalizar las columnas de este marco de datos donde cada valor está entre 0 y 1?
Mi resultado deseado es:
A B C
1 1 1
0.765 0.5 0.7
0.8 0.7 0.18(which is 0.09/0.5)
una manera fácil usando Pandas : (aquí quiero usar la normalización media)
normalized_df=(df-df.mean())/df.std()
para usar la normalización min-max:
normalized_df=(df-df.min())/(df.max()-df.min())
Editar: para abordar algunas inquietudes, debo decir que Pandas aplica automáticamente la función de columnas en el código anterior.
Puede utilizar el paquete sklearn y sus utilidades de preprocesamiento asociadas para normalizar los datos.
import pandas as pd
from sklearn import preprocessing
x = df.values #returns a numpy array
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df = pd.DataFrame(x_scaled)
Para obtener más información, consulte la documentación de scikit-learn sobre preprocesamiento de datos: escalamiento de funciones a un rango.
Ejemplo detallado de métodos de normalización
- Normalización de Pandas (imparcial)
- Normalización de Sklearn (sesgada)
- ¿Afecta el aprendizaje automático sesgado versus imparcial?
- Escalado mixto máximo
Referencias: Wikipedia: Estimación insesgada de la desviación estándar
Datos de ejemplo
import pandas as pd
df = pd.DataFrame({
'A':[1,2,3],
'B':[100,300,500],
'C':list('abc')
})
print(df)
A B C
0 1 100 a
1 2 300 b
2 3 500 c
Normalización utilizando pandas (proporciona estimaciones imparciales)
Al normalizar simplemente restamos la media y dividimos por la desviación estándar.
df.iloc[:,0:-1] = df.iloc[:,0:-1].apply(lambda x: (x-x.mean())/ x.std(), axis=0)
print(df)
A B C
0 -1.0 -1.0 a
1 0.0 0.0 b
2 1.0 1.0 c
Normalización usando sklearn (proporciona estimaciones sesgadas, diferentes de los pandas)
¡Si haces lo mismo sklearn
obtendrás un resultado DIFERENTE!
import pandas as pd
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df = pd.DataFrame({
'A':[1,2,3],
'B':[100,300,500],
'C':list('abc')
})
df.iloc[:,0:-1] = scaler.fit_transform(df.iloc[:,0:-1].to_numpy())
print(df)
A B C
0 -1.224745 -1.224745 a
1 0.000000 0.000000 b
2 1.224745 1.224745 c
¿Las estimaciones sesgadas de sklearn hacen que el aprendizaje automático sea menos poderoso?
NO.
La documentación oficial de sklearn.preprocessing.scale establece que es PROBABLE que el uso de un estimador sesgado afecte el rendimiento de los algoritmos de aprendizaje automático y podemos usarlos de forma segura.
De la documentación oficial:
Utilizamos un estimador sesgado para la desviación estándar, equivalente a
numpy.std(x, ddof=0)
. Tenga en cuenta que es poco probable que la elección deddof
afecte el rendimiento del modelo.
¿Qué pasa con la escala MinMax?
No hay cálculo de desviación estándar en la escala MinMax. Entonces el resultado es el mismo tanto en pandas como en scikit-learn.
import pandas as pd
df = pd.DataFrame({
'A':[1,2,3],
'B':[100,300,500],
})
(df - df.min()) / (df.max() - df.min())
A B
0 0.0 0.0
1 0.5 0.5
2 1.0 1.0
# Using sklearn
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
arr_scaled = scaler.fit_transform(df)
print(arr_scaled)
[[0. 0. ]
[0.5 0.5]
[1. 1. ]]
df_scaled = pd.DataFrame(arr_scaled, columns=df.columns,index=df.index)
print(df_scaled)
A B
0 0.0 0.0
1 0.5 0.5
2 1.0 1.0
Basado en esta publicación: https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range
Puedes hacer lo siguiente:
def normalize(df):
result = df.copy()
for feature_name in df.columns:
max_value = df[feature_name].max()
min_value = df[feature_name].min()
result[feature_name] = (df[feature_name] - min_value) / (max_value - min_value)
return result
No necesitas seguir preocupándote por si tus valores son negativos o positivos. Y los valores deberían estar bien distribuidos entre 0 y 1.