规范化数据框的列
- 2025-02-08 08:52:00
- admin 原创
- 57
问题描述:
我在 Pandas 中有一个数据框,其中每列都有不同的值范围。例如:
数据:
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)
解决方案 1:
一种简单的方法是使用Pandas :(这里我想使用均值标准化)
normalized_df=(df-df.mean())/df.std()
使用最小-最大规范化:
normalized_df=(df-df.min())/(df.max()-df.min())
编辑:为了解决一些问题,需要说 Pandas 在上面的代码中自动应用了按列的函数。
解决方案 2:
您可以使用 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文档:将特征缩放到一定范围。
解决方案 3:
规范化方法的详细示例
Pandas 规范化(无偏)
Sklearn 规范化(有偏见)
有偏见与无偏见会影响机器学习吗?
混合最大缩放
参考文献:
维基百科:标准差的无偏估计
示例数据
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 进行规范化(给出有偏差的估计,与 pandas 不同)
如果你做同样的事情,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 怎么样?
MinMax 缩放中没有标准偏差计算。因此 pandas 和 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
解决方案 4:
根据这篇文章: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 之间。
解决方案 5:
您的问题实际上是对列进行简单的转换:
def f(s):
return s/s.max()
frame.apply(f, axis=0)
或者更简洁一点:
frame.apply(lambda x: x/x.max(), axis=0)
解决方案 6:
如果你喜欢使用 sklearn 包,你可以使用 pandas 保留列和索引名称,loc
如下所示:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled_values = scaler.fit_transform(df)
df.loc[:,:] = scaled_values
解决方案 7:
请谨慎回答此问题,因为它仅适用于范围为 [0, n] 的数据。它不适用于任何范围的数据。
简单就是美:
df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()
解决方案 8:
您可以创建要规范化的列的列表
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 Dataframe 现在仅在您想要的列上进行规范化
但是,如果您想要相反的结果,选择您不想规范化的列的列表,您可以简单地创建所有列的列表并删除不需要的列
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 ]
解决方案 9:
规格化
您可以使用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_scale
或scale
之后 train_test_split
以避免数据泄露。
信息
有关标准化和规范化的更多信息:
https://machinelearningmastery.com/standardscaler-and-minmaxscaler-transforms-in-python/
https://scikit-learn.org/stable/modules/classes.html#module-sklearn.preprocessing
解决方案 10:
我认为在 Pandas 中更好的方法是
df = df/df.max().astype(np.float64)
编辑如果数据框中存在负数,则应使用
df = df/df.loc[df.abs().idxmax()].astype(np.float64)
解决方案 11:
Sandman 和 Praveen 给出的解决方案非常好。唯一的问题是,如果您的数据框的其他列中有分类变量,则此方法需要进行一些调整。
我对此类问题的解决方案如下:
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])
解决方案 12:
您可能希望对某些列进行规范化,而其他列保持不变,例如某些回归任务,其数据标签或分类列保持不变,因此我建议您使用这种 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()))
解决方案 13:
这只是简单的数学。答案应该如下所示。
normed_df = (df - df.min()) / (df.max() - df.min())
解决方案 14:
df_normalized = df / df.max(axis=0)
解决方案 15:
您可以简单地按以下方式使用 pandas.DataFrame.transform 1函数:
df.transform(lambda x: x/x.max())
解决方案 16:
以下是使用列表推导按列执行的操作:
[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]
解决方案 17:
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 的输入轴应用函数。传递给函数的对象是 Series 对象,其索引为 DataFrame 的索引(axis=0)或列(axis=1)。返回类型取决于传递的函数是否聚合,或者如果 DataFrame 为空则为 Reduce 参数。
您可以应用自定义函数来操作 DataFrame 。
解决方案 18:
以下函数计算 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
解决方案 19:
新的 Scikit-Learn(版本> = 1.2):保留 DataFrame 列名称
在新版本的 scikit-learn 中,现在实际上可以在转换之后保持 pandas 列名不变,下面是示例:
>>> import pandas as pd
>>> from sklearn.preprocessing import MinMaxScaler, MaxAbsScaler
>>> df = pd.DataFrame({'col1':[1000, 765, 800], 'col2':[10, 5, 7], 'col3':[0.5, 0.35, 0.09]}, )
>>> df.head(3)
col1 col2 col3
0 1000 10 0.50
1 765 5 0.35
2 800 7 0.09
>>> scaler = MaxAbsScaler().set_output(transform="pandas") #change here
>>> scaler.fit(df)
>>> df_scaled = scaler.transform(df)
>>> df_scaled.head(3)
col1 col2 col3
0 1.000 1.0 1.00
1 0.765 0.5 0.70
2 0.800 0.7 0.18
我在这里写了新更新的摘要,您也可以查看 scikit-learn发布亮点页面。
另外,我个人从来都不是 MaxAbsScaler 的忠实粉丝,但我选择这个来回答 op 的问题。
希望这有帮助,加油!!
解决方案 20:
您只需一行即可完成此操作
DF_test = DF_test.sub(DF_test.mean(axis=0), axis=1)/DF_test.mean(axis=0)
它取每一列的平均值,然后从每一行中减去它(平均值)(特定列的平均值仅从其行中减去)并仅除以平均值。最后,我们得到的是标准化数据集。
解决方案 21:
Pandas 默认进行逐列规范化。尝试以下代码。
X= pd.read_csv('.\\data.csv')
X = (X-X.min())/(X.max()-X.min())
输出值在 0 到 1 的范围内。
解决方案 22:
嘿,使用带有 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))
解决方案 23:
仅使用本机 Python 来规范化 DataFrame 列。
不同的价值观会影响过程,例如绘制颜色。
0
至之间1
:
min_val = min(list(df['col']))
max_val = max(list(df['col']))
df['col'] = [(x - min_val) / max_val for x in df['col']]
至-1
之间1
:
df['col'] = [float(i)/sum(df['col']) for i in df['col']]
或者
df['col'] = [float(tp) / max(abs(df['col'])) for tp in df['col']]
解决方案 24:
df.normalize()
到现在为止,这个帖子已经有 9 年多了。
我不确定 pandas 何时添加了这个 func()。
对于我来说,进行定量分析似乎很有效果。
解决方案 25:
如果您的数据呈正偏态,则最好的规范化方法是使用对数转换:
df = np.log10(df)