2016-10-12 63 views
2

我有一個大熊貓數據框(df_orig)和幾個查找表(也是數據框),它們對應於df_orig中的每個段。基於Python中的多個查找表創建一個新的列Pandas

這裏是df_orig一小部分:

segment score1 score2 
B3   0 700 
B1   0 120 
B1  400 950 
B1  100 220 
B1  200 320 
B1  650 340 
B5  300 400 
B5   0 320 
B1   0 240 
B1  100 360 
B1  940 700 
B3  100 340 

而這裏將其全部段B5查找表稱爲thresholds_b5(有在大型數據集中的每個段的查找表):

score1 score2 
990  220 
980  280 
970  200 
960  260 
950  260 
940  200 
930  240 
920  220 
910  220 
900  220 
850  120 
800  220 
750  220 
700  120 
650  200 
600  220 
550  220 
500  240 
400  240 
300  260 
200  300 
100  320 
    0  400 

我要創造我的大型數據集的新列很是類似這樣的SQL邏輯:

case when segment = 'B5' then 
    case when score1 = 990 and score2 >= 220 then 1 
    case when score1 = 980 and score2 >= 280 then 1 
    . 
    . 
    . 
    else 0 
case when segment = 'B1' then 
. 
. 
. 
else 0 end as indicator 

我能得到使用基於解決方案的環路的正確輸出this question

df_b5 = df_orig[df_orig.loc[:,'segment'] == 'B5'] 

for i,row in enumerate(thresholds_b5): 

    value1 = thresholds_b5.iloc[i,0] 
    value2 = thresholds_b5.iloc[i,1] 

    df_b5.loc[(df_b5['score1'] == value1) & (df_b5['score2'] >= value2), 'indicator'] = 1 

不過,我需要另一個循環到各段運行這個再追加所有結果dataframes的回到一起,這有點凌亂。此外,雖然我現在只有三個細分市場(B1,B3,B5),但我將來會有20多個細分市場。

有沒有辦法做到這一點更簡潔,最好沒有循環?我已經被警告過,數據幀上的循環往往很慢,考慮到我的數據集的大小,我認爲速度很重要。

回答

2

如果您沒有問題的時間提前分揀DataFrames,那麼你就可以用新的asof join in pandas 0.19取代你的循環例如:

# query 
df_b5 = df_orig.query('segment == "B5"') 

# sort ahead of time 
df_b5.sort_values('score2', inplace=True) 
threshold_b5.sort_values('score2', inplace=True) 

# set the default indicator as 1 
threshold_b5['indicator'] = 1 

# join the tables 
df = pd.merge_asof(df_b5, threshold_b5, on='score2', by='score1') 

# fill missing indicators as 0 
df.indicator = np.int64(df.indicator.fillna(0.0)) 

這是我得到:

segment score1 score2 indicator 
0  B5  0  320   0 
1  B5  300  400   1 

如果您需要原始訂單,然後將索引保存在df_orig的新列中,然後通過該索引最終獲取DataFrame。


pandas 0.19.2 added multiple by parameters,所以你可以concat都與每個人的segment列集的閾值,然後調用:

pd.merge_asof(df_orig, thresholds, on='score2', by=['segment', 'score1']) 
+2

哇!這真的是一個非常有用的新功能! – MaxU

+0

非常感謝!爲了確保我的理解,我仍然需要一個循環來運行'df_orig ['segment']。unique()'中的每個段的代碼,給出多個參數的限制,對吧? –

+0

@ D.Ross這是正確的。目前,您在唯一細分受衆羣上的外部環路將保持不變。 – chrisaycock

相關問題