在pandas数据帧中向前填充函数nans的快速方法

时间:2018-01-24 11:10:47

标签: python performance pandas dataframe

我有一个带有整数值的稀疏数据帧。例如,我们将df创建为

df = pd.DataFrame(np.nan, index=range(10), columns=['A', 'B', 'C'])
df.loc[(0,'A')] = 6
df.loc[(3,'A')] = 8
df.loc[(4,'B')] = 2

它看起来像这个

    A   B   C
0   6 NaN NaN
1 NaN NaN NaN
2 NaN NaN NaN
3   8 NaN NaN
4 NaN   2 NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 NaN NaN NaN
8 NaN NaN NaN
9 NaN NaN NaN

现在我想递归地用前一个值-1填充每个nan值(如果它不是nan)。例如,这段代码可以解决问题:

for j in range(len(df.index)):
    df = df.fillna(value=df.shift(1)-1, limit=1)

并生成

   A   B   C
0  6 NaN NaN
1  5 NaN NaN
2  4 NaN NaN
3  8 NaN NaN
4  7   2 NaN
5  6   1 NaN
6  5   0 NaN
7  4  -1 NaN
8  3  -2 NaN
9  2  -3 NaN

问题是这个代码适用于"真正的"即使我有j的范围,数据帧仍然很慢。由于它看起来非常接近简单的df.fillna(method='ffill'),速度更快,我想知道是否有办法加速这个过程。

提前感谢您的回答,见解或评论。

2 个答案:

答案 0 :(得分:2)

这不是一般解决方案,但应在特定情况下产生预期输出:

for col in df.columns:
    g = df[col].notnull().cumsum()
    df[col] = df[col].fillna(method='ffill') - df[col].groupby(g).cumcount()

基本上你填写前,然后减去最后一个非空值后连续nans的数量。

答案 1 :(得分:0)

我对您的玩具问题的比较表明,下面的代码比您的代码更快,而且接受的答案也是如此;您的里程可能因您的实际问题而异。

for col,series in df.iteritems():
    reference = series[0]
    for idx,val in series.iteritems():
        if np.isnan(val):
            reference = reference - 1
            series[idx] = reference
        else:
            reference = val