2017-08-29 78 views
2

我有數據被分組,並且分成了訓練和測試集。我正在計算z的分數。在訓練集上,這很容易,因爲我可以使用內置函數來計算平均值和標準偏差。在Pandas的測試數據框中查找數據的z分數

下面是一個例子,在這裏我要尋找的z分數由地方: 進口大熊貓作爲PD 進口numpy的爲NP #我的示例數據幀

train = pd.DataFrame({'place':  ['Winterfell','Winterfell','Winterfell','Winterfell','Dorne', 'Dorne','Dorne'], 
         'temp' : [ 23 , 10 , 0 , -32, 90, 110, 100 ]}) 
test = pd.DataFrame({'place': ['Winterfell', 'Winterfell', 'Dorne'], 
         'temp' : [6, -8, 100]}) 

# get the z-scores by group for the training set 
train.loc[: , 'z' ] = train.groupby('place')['temp'].transform(lambda x: (x - x.mean())/x.std()) 

現在的訓練數據框的形式爲:

| Place | temp | z | 
|------------|------|-------| 
| Winterfell | 23| 0.969 | 
| Winterfell | 10| 0.415 | 
| Winterfell |  0|-0.011 | 
| Winterfell | -32|-1.374 | 
|  Dorne | 90| 1.000 | 
|  Dorne | 110|-1.000 | 
|  Dorne | 100| 0.000 | 

這就是我想要的。

問題是我現在想用訓練集的平均值和標準差來計算測試集中的z分數。我能得到的平均值和標準偏差足夠容易:

summary = train.groupby('place').agg({'temp' : [np.mean, np.std]}).xs('temp',axis=1,drop_level=True) 

print(summary) 

      mean  std 
place       
Dorne  100.00 10.000000 
Winterfell 0.25 23.471614 

我做我想要的東西的一些複雜的方式,但由於這是一個任務,我必須經常做,我找做的一個整潔的方式它。以下是我迄今爲止嘗試:

  1. 製作一本字典dict出彙總表,在那裏我可以提取均值和標準devation作爲一個元組。然後在測試集,我可以做一個適用於:

    test.loc[: , 'z'] = test.apply(lambda row: (row.temp - dict[row.place][0])/dict[row.place][1] ,axis = 1) 
    

爲什麼我不喜歡它:

  • 字典使得它難以閱讀,需要知道什麼結構dict是。
  • 如果某個地方出現在測試集中,而不是訓練集中,而不是獲得NaN,則代碼將引發錯誤。

  • 使用索引

    test.set_index('place', inplace = True) 
    test.loc[:, 'z'] = (test['temp'] - summary['mean'])/summary['std'] 
    

爲什麼我不喜歡它: - 看起來像它應該工作,而是給了我只有NaNs

最終結果應該是 是否有標準pythonic方式做這種組合?

+0

這樣的回答可以幫助你:HTTPS://stackoverflow.com/questions/ 2476 1998/pandas-compute-z-score-for-all-columns – jvk777

+0

謝謝!我在構思解決方案時看到了其中一個,儘管那個人專注於從數據框中的數據計算z-分數,而不是使用來自單獨數據框的方法。 雖然,時間序列示例接近做我在找的東西。 –

回答

3

選項1
pd.Series.map

test.assign(z= 
    (test.temp - test.place.map(summary['mean']))/test.place.map(summary['std']) 
) 

     place temp   z 
0 Winterfell  6 0.244977 
1 Winterfell -8 -0.351488 
2  Dorne 100 0.000000 

選項2
pd.DataFrame.eval

test.assign(z= 
    test.join(summary, on='place').eval('(temp - mean)/std') 
) 

     place temp   z 
0 Winterfell  6 0.244977 
1 Winterfell -8 -0.351488 
2  Dorne 100 0.000000 
+0

謝謝!這正是我所期待的。 –

+0

@DamienMartin歡迎您。 – piRSquared

+2

選項2是一個有趣的應用程序,在'臨時連接上''assign'和'eval'一起使用。 – Alexander