我有一个带有整数值的稀疏数据帧。例如,我们将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')
,速度更快,我想知道是否有办法加速这个过程。
提前感谢您的回答,见解或评论。
答案 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