规范化数据框架的列

我有一个熊猫的数据框架,其中每一列都有不同的值范围。例如:

df:

A     B   C
1000  10  0.5
765   5   0.35
800   7   0.09

知道我如何规范化这个数据框架的列,其中每个值都在0到1之间吗?

我想要的输出是:

A     B    C
1     1    1
0.765 0.5  0.7
0.8   0.7  0.18(which is 0.09/0.5)
876439 次浏览

您可以使用sklearn包及其相关的预处理实用程序来规范化数据。

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)

有关更多信息,请参阅关于预处理数据的scikit-learn 文档:将特征缩放到一个范围。

你的问题实际上是一个作用于列的简单变换:

def f(s):
return s/s.max()


frame.apply(f, axis=0)

或者更简洁:

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

我认为在熊猫身上更好的方法是

df = df/df.max().astype(np.float64)

编辑如果在你的数据帧中出现负数,你应该使用

df = df/df.loc[df.abs().idxmax()].astype(np.float64)

基于本文:https://stats.stackexchange.com/questions/70801/how-to-normalize-data-to-0-1-range

您可以执行以下操作:

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

你不需要一直担心你的价值观是积极的还是消极的。这些值应该很好地分布在0和1之间。

一个简单的方法是使用熊猫:(这里我想使用均值归一化)

normalized_df=(df-df.mean())/df.std()

使用最小-最大归一化:

normalized_df=(df-df.min())/(df.max()-df.min())

编辑:为了解决一些问题,需要说明Pandas在上面的代码中自动应用列函数。

如果你喜欢使用sklearn包,你可以像这样使用pandas loc来保留列名和索引名:

from sklearn.preprocessing import MinMaxScaler


scaler = MinMaxScaler()
scaled_values = scaler.fit_transform(df)
df.loc[:,:] = scaled_values

睡魔和普拉文给出的解决方案很好。唯一的问题是,如果你在数据帧的其他列中有分类变量,这种方法将需要一些调整。

我对这类问题的解决方案如下:

 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])

注意这个答案,因为它只适用于范围为[0,n]的数据。这对任何范围的数据都不起作用。


简单就是美:

df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()
def normalize(x):
try:
x = x/np.linalg.norm(x,ord=1)
return x
except :
raise
data = pd.DataFrame.apply(data,normalize)

根据pandas的文档,DataFrame结构可以对自身应用操作(函数)。

DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

应用函数沿数据帧的输入轴。 传递给函数的对象是具有DataFrame的索引(轴=0)或列(轴=1)索引的Series对象。返回类型取决于所传递的函数是否聚合,如果DataFrame为空则返回reduce参数

您可以应用自定义函数来操作DataFrame。

您可以创建一个列的列表,您想规范化

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

你的Pandas数据帧现在只在你想要的列上标准化


然而,如果你想要相反,选择一个你想要规范化的列列表,你可以简单地创建一个所有列的列表,并删除那些不需要的列

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 ]

下面的函数计算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

你可以在一行中完成

DF_test = DF_test.sub(DF_test.mean(axis=0), axis=1)/DF_test.mean(axis=0)

它取每一列的平均值,然后从每一行中减去它(平均值)(特定列的平均值仅从该行中减去),然后仅除以平均值。最后,我们得到的是规范化的数据集。

你可能想让一些列被标准化,而其他的列是不变的,比如一些回归任务,数据标签或分类列是不变的,所以我建议你用这种python的方式(它是@shg和@Cina答案的组合):

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()))

归一化方法的详细示例

  • 熊猫正常化(无偏)
  • Sklearn归一化(有偏)
  • 有偏见vs无偏见会影响机器学习吗?
  • Mix-max扩展
< p >引用: 维基百科:标准偏差的无偏估计 < / p >

示例数据

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

使用熊猫进行标准化(给出无偏倚的估计)

当归一化时,我们只需减去平均值并除以标准差。

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

使用sklearn进行标准化(给出有偏差的估计,与熊猫不同)

如果你对sklearn做同样的事情,你会得到不同的输出!

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

对sklearn有偏见的估计会降低机器学习的能力吗?

不。

sklearn.preprocessing.scale的官方文档声明,使用偏估计器不太可能影响机器学习算法的性能,我们可以安全地使用它们。

来自官方文件:

我们对标准偏差使用一个偏估计量,相当于numpy.std(x, ddof=0)。注意,ddof的选择不太可能影响模型性能。

那MinMax Scaling呢?

在最小最大值缩放中没有标准偏差计算。所以熊猫和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

这是你如何使用列表推导式来做的:

[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]

这只是简单的数学。答案应该如下所示。

normed_df = (df - df.min()) / (df.max() - df.min())

你可以简单地使用pandas.DataFrame。transform1函数如下所示:

df.transform(lambda x: x/x.max())

Pandas默认情况下按列进行归一化。试试下面的代码。

X= pd.read_csv('.\\data.csv')
X = (X-X.min())/(X.max()-X.min())

输出值将在0和1的范围内。

df_normalized = df / df.max(axis=0)

如果你的数据是正倾斜的,最好的归一化方法是使用对数变换:

df = np.log10(df)

嘿,使用带有lambda的apply函数来加速这个过程:

def normalize(df_col):


# Condition to exclude 'ID' and 'Class' feature
if (str(df_col.name) != str('ID') and str(df_col.name)!=str('Class')):
max_value = df_col.max()
min_value = df_col.min()


#It avoids NaN and return 0 instead
if max_value == min_value:
return 0


sub_value = max_value - min_value
return np.divide(np.subtract(df_col,min_value),sub_value)
else:
return df_col


df_normalize = df.apply(lambda x :normalize(x))

正常化

可以使用minmax_scale将每一列转换为0-1的刻度。

from sklearn.preprocessing import minmax_scale
df[:] = minmax_scale(df)

标准化

你可以使用scale将每一列居中到平均值,并缩放到单位方差。

from sklearn.preprocessing import scale
df[:] = scale(df)

列的子集

归一化单列

from sklearn.preprocessing import minmax_scale
df['a'] = minmax_scale(df['a'])

只归一化数值列

import numpy as np
from sklearn.preprocessing import minmax_scale
cols = df.select_dtypes(np.number).columns
df[cols] = minmax_scale(df[cols])

完整的示例

# Prep
import pandas as pd
import numpy as np
from sklearn.preprocessing import minmax_scale


# Sample data
df = pd.DataFrame({'a':[0,1,2], 'b':[-10,-30,-50], 'c':['x', 'y', 'z']})


# MinMax normalize all numeric columns
cols = df.select_dtypes(np.number).columns
df[cols] = minmax_scale(df[cols])


# Result
print(df)


#    a    b  c
# 0  0.0  1.0  x
# 2  0.5  0.5  y
# 3  1.0  0.0  z

注:

在所有示例中,都可以使用scale来代替minmax_scale。保持索引、列名或非数值变量不变。函数应用于每一列。

警告:

对于机器学习,可以使用minmax_scalescale train_test_split来避免数据泄露。

信息

更多关于标准化和规范化的信息: