2012-09-21 104 views
78

假設我有一個熊貓數據幀df數據標準化

我要計算一個數據幀的逐列平均值。

這是容易的:

df.apply(average) 

然後逐列範圍內的最高(COL) - 最小(COL)。這又是很容易:

df.apply(max) - df.apply(min) 

現在對於我希望通過其列的範圍內減去其列的平均值,然後除以每個元素。我不知道該怎麼做

任何幫助/指針非常感謝。

回答

143
In [92]: df 
Out[92]: 
      a   b   c   d 
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]: 
      a   b   c   d 
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 
+14

這是如此明顯,我的思想不能接受它:) – jason

+0

有沒有辦法做到這一點,如果你想正常化的子集?假設「A」和「B」行是您想要與「C」和「D」分開歸一化的更大分組因子的一部分。 – Amyunimus

+0

像以前一樣選擇子集並進行計算。關於如何索引和選擇數據,請參閱http://pandas.pydata.org/pandas-docs/stable/indexing.html –

23

您可以使用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 

而且,它與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 
48

如果您不介意導入sklearn庫,我會推薦在this博客上討論的方法。

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 
+2

到博客帖子的鏈接已經死亡。你有工作嗎? – marts

+0

@marts完成...! – astrojuanlu

+3

創建單位正態歸一化數據的相應方法稱爲StandardScaler。 – abeboparebop

2

從稍加修改:Python Pandas Dataframe: Normalize data between 0.01 and 0.99?但一些評論認爲這是相關的(對不起,如果認爲是轉貼,雖然...)

我想在基準或z的,經常百分定製正常化分數不夠。有時候我知道人口的可行最大和最小值是什麼,因此想要定義它,而不是我的樣本,或者不同的中點,或者其他任何東西!這通常對於神經網絡的數據重新縮放和標準化非常有用,您可能希望所有輸入介於0和1之間,但某些數據可能需要以更加自定義的方式進行縮放......因爲百分比和stdevs假設您的樣本覆蓋人口,但有時我們知道這是不正確的。在熱圖中可視化數據對我來說也非常有用。所以,我建立了一個自定義函數(用在代碼中加入額外步驟,在這裏,使其儘可能地易讀):

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 

這將需要在熊貓系列,甚至只是一個列表,並將其歸到自己指定的低,中心和高點。還有一個收縮因素!以允許您將數據從端點0和1中縮小(我必須在matplotlib中將色彩圖組合在一起時執行此操作):因此,您可能會看到代碼的工作方式,但基本上說您具有值[-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] 

它也可以把裏面你的數據...這似乎很奇怪,但我發現它有用heatmapping。假設你想要一個更接近0的值而不是hi/low值較深的顏色。你可以熱圖基於標準化的數據,其中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」爲最高值。

無論如何,我認爲我的應用程序是相關的,如果你想以其他方式重新調整數據,可能會有用的應用程序給你。

+0

你可以用[帶有函數的字典]替換所有的if/else語句(https://stackoverflow.com/questions/60208/replacements-for-switch-statement-in-python)。看起來更清潔一點。 – Roald

+0

非常整齊,下次我會記住這一點,謝謝! – Vlox