在pandas中标准化数据
假设我有一个pandas数据框df:
我想计算一个dataframe的列明智的意思,
这很容易:
df.apply(average)
那么列明智的范围最大(col) – min(col)。 这又很容易:
df.apply(max) - df.apply(min)
现在对于每个元素,我想减去它的列平均值,并除以列的范围。 我不知道该怎么做
任何帮助/指针非常感谢。
In [92]: df Out[92]: abcd A -0.488816 0.863769 4.325608 -4.721202 B -11.937097 2.993993 -12.916784 -1.086236 C -5.569493 4.672679 -2.168464 -9.315900 D 8.892368 0.932785 4.535396 0.598124 In [93]: df_norm = (df - df.mean()) / (df.max() - df.min()) In [94]: df_norm Out[94]: abcd A 0.085789 -0.394348 0.337016 -0.109935 B -0.463830 0.164926 -0.650963 0.256714 C -0.158129 0.605652 -0.035090 -0.573389 D 0.536170 -0.376229 0.349037 0.426611 In [95]: df_norm.mean() Out[95]: a -2.081668e-17 b 4.857226e-17 c 1.734723e-17 d -1.040834e-17 In [96]: df_norm.max() - df_norm.min() Out[96]: a 1 b 1 c 1 d 1
如果你不介意导入sklearn
库,我会推荐在这个博客上讨论的方法。
import pandas as pd from sklearn import preprocessing data = {'score': [234,24,14,27,-74,46,73,-18,59,160]} df = pd.DataFrame(data) df min_max_scaler = preprocessing.MinMaxScaler() np_scaled = min_max_scaler.fit_transform(df) df_normalized = pd.DataFrame(np_scaled) df_normalized
你可以使用apply
,这是一个整洁:
import numpy as np import pandas as pd np.random.seed(1) df = pd.DataFrame(np.random.randn(4,4)* 4 + 3) 0 1 2 3 0 9.497381 0.552974 0.887313 -1.291874 1 6.461631 -6.206155 9.979247 -0.044828 2 4.276156 2.002518 8.848432 -5.240563 3 1.710331 1.463783 7.535078 -1.399565 df.apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) 0 1 2 3 0 0.515087 0.133967 -0.651699 0.135175 1 0.125241 -0.689446 0.348301 0.375188 2 -0.155414 0.310554 0.223925 -0.624812 3 -0.484913 0.244924 0.079473 0.114448
另外,如果您select相关的列,它与groupby
很好地groupby
:
df['grp'] = ['A', 'A', 'B', 'B'] 0 1 2 3 grp 0 9.497381 0.552974 0.887313 -1.291874 A 1 6.461631 -6.206155 9.979247 -0.044828 A 2 4.276156 2.002518 8.848432 -5.240563 B 3 1.710331 1.463783 7.535078 -1.399565 B df.groupby(['grp'])[[0,1,2,3]].apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) 0 1 2 3 0 0.5 0.5 -0.5 -0.5 1 -0.5 -0.5 0.5 0.5 2 0.5 0.5 0.5 -0.5 3 -0.5 -0.5 -0.5 0.5
稍微修改: Python Pandas Dataframe:在0.01和0.99之间规范化数据? 但从一些评论认为这是相关的(对不起,如果考虑重新发布虽然…)
我想定制的规范化,在正常的百分位数据或z分数是不够的。 有时候我知道可行的最大和最小的人口是什么,因此想要定义它,而不是我的样本,或不同的中点,或任何其他! 这通常可以用于neural network的数据重新缩放和标准化,您可能希望所有的input都在0和1之间,但是一些数据可能需要以更加自定义的方式进行缩放……因为百分比和stdevs假设您的样本覆盖人口,但有时我们知道这是不正确的。 在热图中可视化数据对我来说也是非常有用的。 所以我build立了一个自定义函数(在代码中使用额外的步骤使其尽可能可读):
def NormData(s,low='min',center='mid',hi='max',insideout=False,shrinkfactor=0.): if low=='min': low=min(s) elif low=='abs': low=max(abs(min(s)),abs(max(s)))*-1.#sign(min(s)) if hi=='max': hi=max(s) elif hi=='abs': hi=max(abs(min(s)),abs(max(s)))*1.#sign(max(s)) if center=='mid': center=(max(s)+min(s))/2 elif center=='avg': center=mean(s) elif center=='median': center=median(s) s2=[x-center for x in s] hi=hi-center low=low-center center=0. r=[] for x in s2: if x<low: r.append(0.) elif x>hi: r.append(1.) else: if x>=center: r.append((x-center)/(hi-center)*0.5+0.5) else: r.append((x-low)/(center-low)*0.5+0.) if insideout==True: ir=[(1.-abs(z-0.5)*2.) for z in r] r=ir rr =[x-(x-0.5)*shrinkfactor for x in r] return rr
这将采取pandas系列,甚至只是一个列表,并将其规范化到您指定的低点,中点和高点。 还有一个收缩因素! 允许你将数据从端点0和1中缩小(我必须在matplotlib中结合彩色地图时执行此操作: 使用Matplotlib将单个pcolormesh与多个颜色地图结合使用 )所以,您可能会看到代码如何工作,但基本上会说样本中的值为[-5,1,10],但是想要基于-7到7的范围进行归一化(因此高于7的任何值,我们的“10”被有效地视为7),中点为2,但缩小到适合256 RGB的颜色映射:
#In[1] NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256) #Out[1] [0.1279296875, 0.5826822916666667, 0.99609375]
它也可以把你的数据里面…这可能看起来很奇怪,但我发现它对热映射有用。 假设你想要一个更接近0而不是高/低值的颜色较深。 你可以根据标准化的数据来加热贴图,其中insideout = True:
#In[2] NormData([-5,2,10],low=-7,center=1,hi=7,insideout=True,shrinkfactor=2./256) #Out[2] [0.251953125, 0.8307291666666666, 0.00390625]
所以,现在最接近中心的“2”,定义为“1”是最高的值。
无论如何,我认为我的应用程序是相关的,如果你正在寻找以其他方式重新调整数据,可能有用的应用程序给你。