Python: escalar números columna por columna con pandas

Tengo un dataframe Pandas ‘df’ en el que me gustaría realizar algunas escalas columna por columna.

  • En la columna ‘a’, necesito que el número máximo sea 1, que el número mínimo sea 0 y que todos los demás se distribuyan en consecuencia.
  • Sin embargo, en la columna ‘b’, necesito que el número mínimo sea 1 , que el número máximo sea 0 y que todos los demás se distribuyan en consecuencia.

¿Hay una función de Pandas para realizar estas dos operaciones? Si no, Numpy sin duda lo haría.

ab A 14 103 B 90 107 C 90 110 D 96 114 E 91 114 

Podrías restar por el mínimo, luego dividir por el máximo (cuidado 0/0). Tenga en cuenta que después de restar el mínimo, el nuevo máximo es el máximo original – mín.

 In [11]: df Out[11]: ab A 14 103 B 90 107 C 90 110 D 96 114 E 91 114 In [12]: df -= df.min() # equivalent to df = df - df.min() In [13]: df /= df.max() # equivalent to df = df / df.max() In [14]: df Out[14]: ab A 0.000000 0.000000 B 0.926829 0.363636 C 0.926829 0.636364 D 1.000000 1.000000 E 0.939024 1.000000 

Para cambiar el orden de una columna (de 1 a 0 en lugar de 0 a 1):

 In [15]: df['b'] = 1 - df['b'] 

Un método alternativo es negar las columnas b primero ( df['b'] = -df['b'] ).

Así es como puedes hacerlo usando sklearn y el módulo de preprocessing . Sci-Kit Learn tiene muchas funciones de preprocesamiento para escalar y centrar datos.

 In [0]: from sklearn.preprocessing import MinMaxScaler In [1]: df = pd.DataFrame({'A':[14,90,90,96,91], 'B':[103,107,110,114,114]}).astype(float) In [2]: df Out[2]: AB 0 14 103 1 90 107 2 90 110 3 96 114 4 91 114 In [3]: scaler = MinMaxScaler() In [4]: df_scaled = pd.DataFrame(scaler.fit_transform(df), columns=df.columns) In [5]: df_scaled Out[5]: AB 0 0.000000 0.000000 1 0.926829 0.363636 2 0.926829 0.636364 3 1.000000 1.000000 4 0.939024 1.000000 

Esto no es muy elegante, pero lo siguiente funciona para este caso de dos columnas:

 #Create dataframe df = pd.DataFrame({'A':[14,90,90,96,91], 'B':[103,107,110,114,114]}) #Apply operates on each row or column with the lambda function #axis = 0 -> act on columns, axis = 1 act on rows #x is a variable for the whole row or column #This line will scale minimum = 0 and maximum = 1 for each column df2 = df.apply(lambda x:(x.astype(float) - min(x))/(max(x)-min(x)), axis = 0) #Want to now invert the order on column 'B' #Use apply function again, reverse numbers in column, select column 'B' only and #reassign to column 'B' of original dataframe df2['B'] = df2.apply(lambda x: 1-x, axis = 1)['B'] 

Si encuentro una forma más elegante (por ejemplo, usando el índice de la columna: (0 o 1) mod 2 – 1 para seleccionar el signo en la operación de aplicación para que se pueda hacer con un solo comando de aplicación, le avisaré) .

En caso de que desee escalar solo una columna en el dataframe, puede hacer lo siguiente:

 from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler() df['Col1_scaled'] = scaler.fit_transform(df['Col1'].values.reshape(-1,1)) 

dado un dataframe

 df = pd.DataFrame({'A':[14,90,90,96,91], 'B':[103,107,110,114,114]}) 

escala con media 0 y var 1

 df.apply(lambda x: (x - np.mean(x)) / np.std(x), axis=0) 

escala con rango entre 0 y 1

 df.apply(lambda x: x / np.max(x), axis=0)