我有一个数据框,其中的列包含NaN值。我想用值填充这些。我想拥有的方法“ ffill”的Fillna()几乎是我想要的东西,但不完全是。我想用最后一个有效值的120%替换我的NaN。因此,如果NaN之前的最后一个有效值为100.0,那么我希望NaN的位置为120.0。
我知道我可以迭代df,但这将需要很多时间。 (我的df目前大约有100.000行,并将进一步增加)
示例: df是我的初始数据框:
df = pd.DataFrame([[np.nan, 2, np.nan, 0], [3, 4, np.nan, 1], [np.nan, np.nan, np.nan, 5], [np.nan, 3, np.nan, 4], [5, 4, 2, np.nan], [np.nan, 3, np.nan, 4]], columns=list('ABCD'))
>>> df
A B C D
0 NaN 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 NaN NaN NaN 5.0
3 NaN 3.0 NaN 4.0
4 5.0 4.0 2.0 NaN
5 NaN 3.0 NaN 4.0
这就是我想要得到的:
>>> df
A B C D
0 NaN 2.0 NaN 0.0
1 3.0 4.0 NaN 1.0
2 3.6 NaN NaN 5.0
3 3.6 3.0 NaN 4.0
4 5.0 4.0 2.0 NaN
5 6.0 3.0 NaN 4.0
因此列“ A”在行num中有两个替换。 2和3,现在的数值均为3.6(3 * 1.2),而不是NaN,加上第5行的更改,其中Nan被替换为6(5 * 1.2) 我一开始并不关心NaN,它们可以留下。我只想在“ A”列中进行更改。
答案 0 :(得分:0)
我建议您使用部分列,以检查它是否是ffill
之前的NaN值
如下:
df['partially_filled_A'] = df['A'].fillna(method='ffill')
df['isNan'] = df['A'].isnull()
df['A_filled'] = np.where((df['isNan']) & (df['partially_filled_A'].isnull() == False), df['partially_filled_A']*1.2, df['A'])
df
我与iteritems
作了一些比较,结果如下:
df = pd.concat([df for _ in range(500_000)]) # let's make a df with 3_000_000 rows for the benchmark
%% time
l = []
last_value = None
for item, frame in df['A'].iteritems():
if last_value is None:
if pd.notnull(frame):
last_value = frame * 1.2
l.append(frame)
else:
l.append(np.nan)
else:
if pd.notnull(frame):
l.append(frame)
last_value = frame * 1.2
else:
l.append(last_value)
df['ans'] = l
# 2.5 seconds
np.where
%%time
df['partially_filled_A'] = df['A'].fillna(method='ffill')
df['isNan'] = df['A'].isnull()
df['A_filled'] = np.where((df['isNan']) & (df['partially_filled_A'].isnull() == False), df['partially_filled_A']*1.2, df['A'])
#100 ms
如本快速基准测试所示,我强烈建议您使用np.where