猿问

结合 bfill() 和 ffill() 功能

说我有以下几点pd.Series:


0     NaN

1     NaN

2     4.0

3     NaN

4     NaN

5     7.0

6     NaN

7     NaN

8     NaN

9     NaN

10    1.0

11    NaN

12    NaN

13    6.0

14    NaN

15    NaN

我试图获得一个系列,其中NaNs由周围的有效样本同样填充。所以说我有N NaNs两个有效样本,我希望第一个N/2 NaNs由最后一个有效样本填充,最后一个N/2 NaNs由下一个有效观察填充。在这种情况下(N % 2) =! 0,额外的观察可以由两个周围的任何一个填充,适用的规则是可以的。所以我想获得:


0     4

1     4

2     4

3     4

4     7

5     7

6     7

7     7

8     1

9     1

10    1

11    1

12    6

13    6

14    6

15    6


皈依舞
浏览 503回答 3
3回答

慕妹3146593

想法是创建布尔面具和过滤bfill用where,然后ffill和最后bfill仅如果通过启动第一系列的第一个值再次NaN:m = df['A'].notna()c = m.cumsum()def f(x):    lens = len(x.index)    a = np.arange(lens)    return a // (lens / 2) == 0mask = c[~m].groupby(c).transform(f)#should be removed#mask = mask.reindex(df.index, fill_value=False)df['B'] = df['A'].where(mask, df['A'].bfill()).ffill().bfill()print (df)      A    B0   NaN  4.01   NaN  4.02   4.0  4.03   NaN  4.04   NaN  7.05   7.0  7.06   NaN  7.07   NaN  7.08   NaN  1.09   NaN  1.010  1.0  1.011  NaN  1.012  NaN  6.013  6.0  6.014  NaN  6.015  NaN  6.0

HUWWW

import pandas as pdwhile pd.isnull(my_series).sum() > 0:&nbsp; &nbsp; my_series = my_series.fillna(method='ffill', limit=1).fillna(method='bfill', limit=1)说这会很慢可能是轻描淡写。如果您想在大型 DataFrame 上执行此操作,我可能会尝试使用我可以使用的函数来实现它apply。我从来没有真正想出这样做的好主意(但我一直在关注这个问题,因为这是一个有趣的问题)。我喜欢另一个聪明的答案,但我很好奇它在速度方面的表现。def funcA(pd_series):&nbsp; &nbsp; m = pd_series.notna()&nbsp; &nbsp; c = m.cumsum()&nbsp; &nbsp; def f(x):&nbsp; &nbsp; &nbsp; &nbsp; lens = len(x.index)&nbsp; &nbsp; &nbsp; &nbsp; a = np.arange(lens)&nbsp; &nbsp; &nbsp; &nbsp; return a // (lens / 2) == 0&nbsp; &nbsp; mask = c[~m].groupby(c).transform(f)&nbsp; &nbsp; #should be removed&nbsp; &nbsp; #mask = mask.reindex(df.index, fill_value=False)&nbsp; &nbsp; return pd_series.where(mask, pd_series.bfill()).ffill().bfill()def funcB(pd_series):&nbsp; &nbsp; while pd.isnull(pd_series).sum() > 0:&nbsp; &nbsp; &nbsp; &nbsp; pd_series = pd_series.fillna(method='ffill', limit=1).fillna(method='bfill', limit=1)&nbsp; &nbsp; return pd_seriesps = pd.Series(np.random.randint(0,10, size=(10000)))ps[ps < 5] = np.nan>>> import timeit>>> timeit.timeit('funcA(ps)', setup='from __main__ import funcA, ps', number=100)40.9788393480012>>> timeit.timeit('funcB(ps)', setup='from __main__ import funcB, ps', number=100)0.4896140840010048嗯......这并不像我期望的那么好。带有半 NaN 的小型系列可能不是一个很好的测试,所以也许尝试一些 while 循环应该阻塞的东西?ps = pd.Series(np.random.randint(0,100, size=(1000000)))ps[ps < 95] = np.nan>>> timeit.timeit('funcA(ps)', setup='from __main__ import funcA, ps', number=10)81.64654629600045>>> timeit.timeit('funcB(ps)', setup='from __main__ import funcB, ps', number=10)21.431495654000173嗯,那至少更接近了。我懒得再扩大规模了,但看起来你可能需要 10^7 个条目和 95%+ NaN 之前屏蔽和安排的额外开销得到回报。
随时随地看视频慕课网APP

相关分类

Python
我要回答