我有一个包含三列的DataFrame,t
,b
和h
:
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
我想避免迭代行,因为我有数百万行。我尝试使用b==True
获取where
个实例,然后使用bfill选项获取fillna
,但无法告诉他何时开始填充。此外,对于apply
中的各个组,这将groupby
,因此我需要一个向其参数添加列并返回整个框架的函数
def get_i(x):
x['i']=x['h'].where(x['b']==True).fillna(value=None,method='backfill').dropna()
return x
答案 0 :(得分: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
答案 1 :(得分: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
请注意我如何使用max
和index < 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