2016-06-07 72 views
2

我有三列,tbh一個數據幀:棘手幀內列邏輯

   t   b   h 
0   NaN  False   6 
1  6.023448  False   38 
2  12.996233  False   46 
3  2.484907  False   67 
4  5.062595  False   81 
5  4.624973  False   82 
6  3.367296  False   38 
7  3.688879  False   53 
8  6.926577  True   38 
9  14.972346  False   81 
10 14.442651  False   78 
11  3.367296  False   67 
12  5.236442  False   46 
13  5.298317  True   8 

,我想以生成用於傳播的h每個實例的值的新列其中b==True倒退,並且只能達到下一個這樣的實例或第一次出現t>9.5。其餘的充滿了NaN的。這裏是我需要的輸出的一個例子:

   t   b   h  i 
0   NaN  False   6  NaN 
1  6.023448  False   38  NaN 
2  12.996233  False   46  38 
3  2.484907  False   67  38 
4  5.062595  False   81  38 
5  4.624973  False   82  38 
6  3.367296  False   38  38 
7  3.688879  False   53  38 
8  6.926577  True   38  38 
9  14.972346  False   81  NaN 
10 14.442651  False   78  8 
11  3.367296  False   67  8 
12  5.236442  False   46  8 
13  5.298317  True   8  8 

我想避免遍歷行,因爲我有他們的數以百萬計。我嘗試使用bfill選項獲得b==True實例where,然後fillna帶有bfill選項,但無法告訴他何時開始填充。此外,這將是apply「ED個別基團的groupby內,所以我需要的功能,增加了一列到它的參數,並返回到整個幀

def get_i(x): 
    x['i']=x['h'].where(x['b']==True).fillna(value=None,method='backfill').dropna() 
    return x 

回答

2

您可以使用:

#create NaN where False values 
df['i'] = np.where(df.b, df.h, np.nan) 
#bfill all NaN 
df['i'] = df.i.fillna(method='bfill') 

#create NaN by condition 
a = df[::-1].groupby('i')['t'].apply(lambda x: (x > 9.5).shift().cumsum()) >= 1 
df['i'] = df.i.mask(a, np.nan) 

print (df) 
      t  b h  i 
0   NaN False 6 NaN 
1 6.023448 False 38 NaN 
2 12.996233 False 46 38.0 
3 2.484907 False 67 38.0 
4 5.062595 False 81 38.0 
5 4.624973 False 82 38.0 
6 3.367296 False 38 38.0 
7 3.688879 False 53 38.0 
8 6.926577 True 38 38.0 
9 14.972346 False 81 NaN 
10 14.442651 False 78 8.0 
11 3.367296 False 67 8.0 
12 5.236442 False 46 8.0 
13 5.298317 True 8 8.0 
+0

很好的解決方案! – MaxU

+0

美觀大方 –

+0

謝謝你的接受。 – jezrael

1

首先,我反向數據幀的順序。它使人們更簡單,對我來說這是沒有必要:

df = df.iloc[::-1] 

爲了隔離在那裏b == True,我添加了一個新列的實例:

df['cum_b'] = df['b'].cumsum() 

這意味着我可以cum_b組分別在每個實例上工作。

我定義了發現的第一個索引,其中,t > 9.5功能,並填充柱i,直到指數:

def func(dfg): 
    idx = max(dfg[dfg.t > 9.5].index, default=-1) 
    dfg.loc[:, 'i'] = dfg.h.iloc[0] 
    dfg.loc[dfg.index < idx, 'i'] = np.nan 
    return dfg.i 

注意我如何使用maxindex < idx,因爲我沒有重置數據框的指數恢復後其順序。

當我申請的功能,我得到你想要的結果:

In [44]: df.groupby('cum_b').apply(func) 
Out[44]: 
cum_b  
1  13  8.0 
     12  8.0 
     11  8.0 
     10  8.0 
     9  NaN 
2  8  38.0 
     7  38.0 
     6  38.0 
     5  38.0 
     4  38.0 
     3  38.0 
     2  38.0 
     1  NaN 
     0  NaN