python - preprocessing - Normalizar columnas de marco de datos de pandas
normalize one column pandas (17)
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 salida deseada 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)
Así es como lo hace en columnas usando la comprensión de la lista:
[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]
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 necesita preocuparse si sus valores son negativos o positivos. Y los valores deben estar bien distribuidos entre 0 y 1.
Creo que una mejor manera de hacerlo en pandas es simplemente
df = df/df.max().astype(np.float64)
Editar Si en su marco de datos hay números negativos, debería usarlos en su lugar
df = df/df.loc[df.abs().idxmax()].astype(np.float64)
Es posible que desee que algunas columnas se normalicen y las otras no se modifiquen, como algunas de las tareas de regresión cuyas etiquetas de datos o columnas categóricas no cambian.
features_to_normalize = [''A'', ''B'', ''C'']
# could be [''A'',''B'']
df[features_to_normalize] = df[features_to_normalize].apply(lambda x:(x-x.min()) / (x.max()-x.min()))
Es solo matemática simple. La respuesta debería ser tan simple como a continuación.
normed_df = (df - df.min()) / (df.max() - df.min())
La siguiente función calcula la puntuación Z:
def standardization(dataset):
""" Standardization of numeric fields, where all values will have mean of zero
and standard deviation of one. (z-score)
Args:
dataset: A `Pandas.Dataframe`
"""
dtypes = list(zip(dataset.dtypes.index, map(str, dataset.dtypes)))
# Normalize numeric columns.
for column, dtype in dtypes:
if dtype == ''float32'':
dataset[column] -= dataset[column].mean()
dataset[column] /= dataset[column].std()
return dataset
La solución dada por Sandman y Praveen está muy bien. El único problema con eso es que si tiene variables categóricas en otras columnas de su marco de datos, este método necesitará algunos ajustes.
Mi solución a este tipo de problema es la siguiente:
from sklearn import preprocesing
x = pd.concat([df.Numerical1, df.Numerical2,df.Numerical3])
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
x_new = pd.DataFrame(x_scaled)
df = pd.concat([df.Categoricals,x_new])
Lo simple es hermoso:
df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()
Puede usar 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 datos de preprocesamiento: funciones de escala a un rango.
Puedes hacer esto en una línea
DF_test = DF_test.sub(DF_test.mean(axis=0), axis=1)/DF_test.mean(axis=0)
toma la media para cada una de las columnas y luego la resta (media) de cada fila (la media de una columna en particular resta solo de su fila) y divide solo por la media. Finalmente, lo que obtenemos es el conjunto de datos normalizado.
Si le gusta usar el paquete sklearn, puede mantener la columna y los nombres de índice usando pandas
loc
así:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled_values = scaler.fit_transform(df)
df.loc[:,:] = scaled_values
Simplemente puede usar la función pandas.DataFrame.transform 1 de esta manera:
df.transform(lambda x: x/x.max())
Su problema es en realidad una simple transformación que actúa sobre las columnas:
def f(s):
return s/s.max()
frame.apply(f, axis=0)
O incluso más conciso:
frame.apply(lambda x: x/x.max(), axis=0)
Tenga en cuenta que sklearn utiliza un estimador sesgado para la desviación estándar. Considere seguir el ejemplo de normalización:
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
Al normalizar, simplemente restamos la media y la dividimos por 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
¡Si haces lo mismo con
sklearn
obtendrás DIFERENTES resultados!
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
Los resultados son diferentes. Sin embargo, según la documentación oficial de sklearn.preprocessing.scale usando estimador sesgado, NO ES PROBABLE que afecte el rendimiento de los algoritmos de aprendizaje automático y podemos usarlos de manera segura.
Una manera fácil mediante el uso de 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())
Puede crear una lista de columnas que desea normalizar.
column_names_to_normalize = [''A'', ''E'', ''G'', ''sadasdsd'', ''lol'']
x = df[column_names_to_normalize].values
x_scaled = min_max_scaler.fit_transform(x)
df_temp = pd.DataFrame(x_scaled, columns=column_names_to_normalize, index = df.index)
df[column_names_to_normalize] = df_temp
Su marco de datos de Pandas ahora está normalizado solo en las columnas que desea
Sin embargo , si desea lo contrario , seleccione una lista de columnas que NO desea normalizar, simplemente puede crear una lista de todas las columnas y eliminar las que no desee.
column_names_to_not_normalize = [''B'', ''J'', ''K'']
column_names_to_normalize = [x for x in list(df) if x not in column_names_to_not_normalize ]
def normalize(x):
try:
x = x/np.linalg.norm(x,ord=1)
return x
except :
raise
data = pd.DataFrame.apply(data,normalize)
Desde el documento de pandas, la estructura DataFrame puede aplicar una operación (función) a sí misma.
DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)
Aplica la función a lo largo del eje de entrada de DataFrame. Los objetos pasados a las funciones son objetos de la Serie que tienen un índice, ya sea el índice del Marco de datos (eje = 0) o las columnas (eje = 1). El tipo de retorno depende de si los agregados de funciones pasados o el argumento de reducción si el DataFrame está vacío.
Puede aplicar una función personalizada para operar el DataFrame.