我有一个pd.Dataframe
,其中有多个缺失值。我只想填充(在这种情况下为回填)我指定下限的时间间隔。我使它与以下代码一起使用。我想知道是否可以避免for循环并加快处理速度(我处理了几百万行)。
import copy
import pandas as pd
# Values
values = [1, 2, 3, 4, float('nan'), float('nan'), float('nan'), 6, 7, 8,
float('nan'), 10, 1, 2, 3, float('nan'), float('nan'), 7]
# Pandas data frame to use
df = pd.DataFrame({'A': values}, index = range(0, len(values)))
# Intervals to fill lower bound list
start_filling_indices = [4, 15]
# Copy the data frame
df_filled = copy.deepcopy(df)
# Filling the intervals
for i in start_filling_indices:
i_stop = df['A'].iloc[i:].first_valid_index()
# +1 is required to include i_stop in the interval
df_filled['A'].iloc[i:i_stop + 1].fillna(method = 'backfill', inplace = True)
这里是没有for循环的解决方案:
首先,我用Start-indices创建一个新的DataFrame,然后我评估在什么索引上我必须更改值,以及将要更改的值。
new=pd.DataFrame({'Start':start_filling_indices})
new['filluntil']=new.apply(lambda row: df.iloc[row.Start:].first_valid_index(),axis=1)
new['indices']=new.apply(lambda row: np.arange(row.Start,row.filluntil),axis=1)
new['fillwith']=new.apply(lambda row: df.A.iloc[row.indices[-1]+1],axis=1)
现在,我使用爆炸功能创建一个新的数据框,该数据框仅包含下一步应更改的行:
new2=new[['indices','fillwith']].explode('indices').set_index('indices')
出于演示目的,我将原始数据复制到DataFrame中的单独列中,然后应用new2-DataFrame中的信息。
df['filled']= copy.deepcopy(df)
df.filled.iloc[test.index]=new2.apply(lambda row: row.fillwith,axis=1)
然后我在一个数据帧中获得原始数据和操作数据
Out:
A filled
0 1.0 1.0
1 2.0 2.0
2 3.0 3.0
3 4.0 4.0
4 NaN 6.0
5 NaN 6.0
6 NaN 6.0
7 6.0 6.0
8 7.0 7.0
9 8.0 8.0
10 NaN NaN
11 10.0 10.0
12 1.0 1.0
13 2.0 2.0
14 3.0 3.0
15 NaN 7.0
16 NaN 7.0
17 7.0 7.0
注意,爆炸功能仅可从Pandas 0.25.0版获得,因为这花了我一些时间才能发现。