我在pandas中有一个数据框,其中每列具有不同的值范围。例如:
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)
您可以使用包sklearn及其关联的预处理实用程序来规范化数据。
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 = pandas.DataFrame(x_scaled)
有关更多信息,请查看有关预处理数据的scikit-learn documentation:将功能扩展到范围。
您可能希望将某些列标准化,而其他列不变,就像数据标签或分类列未更改的某些回归任务所以我建议您使用这种pythonic方式(它是@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()))
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的输入轴应用功能。传递给函数的对象是具有索引的系列对象,索引是DataFrame的索引(轴= 0)或列(轴= 1)。返回类型取决于是否传递函数聚合,如果DataFrame为空,则取决于reduce参数。
您可以应用自定义函数来操作DataFrame。
以下函数计算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)
它取每个列的均值,然后从每一行中减去它(均值)(特定列的平均值仅从其行中减去)并仅除以均值。最后,我们得到的是规范化数据集。
使用Pandas一个简单的方法:(这里我想使用均值归一化)
normalized_df=(df-df.mean())/df.std()
使用min-max规范化:
normalized_df=(df-df.min())/(df.max()-df.min())
基于这篇文章: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之间。
如果你喜欢使用sklearn包,你可以使用像这样的pandas loc
保留列名和索引名:
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
scaled_values = scaler.fit_transform(df)
df.loc[:,:] = scaled_values
你的问题实际上是一个简单的变换作用于列:
def f(s):
return s/s.max()
frame.apply(f, axis=0)
或者更简洁:
frame.apply(lambda x: x/x.max(), axis=0)
简单即美:
df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()
您可以创建要标准化的列的列表
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 ]
我认为在熊猫中做到这一点的更好方法就是
df = df/df.max().astype(np.float64)
编辑如果您的数据框中存在负数,则应使用
df = df/df.loc[df.abs().idxmax()].astype(np.float64)
桑德曼和普拉文给出的解决方案非常好。唯一的问题是,如果您在数据框的其他列中有分类变量,则此方法需要进行一些调整。
我对此类问题的解决方案如下:
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])