
在数据处理过程中,我们经常需要对pandas dataframe中的缺失值(nan)进行填充。然而,在某些特定场景下,填充规则并非全局性,而是依赖于数据中存在的特定标记。例如,我们可能需要将所有位于“start”字符串和“finish”字符串之间的nan值替换为另一个特定字符串(如“check”),而对于不在这些边界内的nan,则保持不变。
传统的ffill()(前向填充)或bfill()(后向填充)方法通常无法直接满足这种有条件的需求。ffill()会将前一个有效值向下传播,而bfill()会将后一个有效值向上回溯,这两种方法都可能填充超出我们期望边界的NaN,或者无法准确界定填充范围。
考虑以下原始DataFrame示例:
import pandas as pd
import numpy as np
data = {'start_finish': ['start', np.nan, np.nan, 'finish', np.nan, np.nan,
'start', np.nan, np.nan, 'start', np.nan, 'finish']}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)输出:
原始DataFrame: start_finish 0 start 1 NaN 2 NaN 3 finish 4 NaN 5 NaN 6 start 7 NaN 8 NaN 9 start 10 NaN 11 finish
我们期望的结果是:
start_finish 0 start 1 check 2 check 3 finish 4 NaN 5 NaN 6 start 7 NaN 8 NaN 9 start 10 check 11 finish
可以看到,只有位于“start”和“finish”之间的NaN(索引1、2和10)被填充为“check”,而其他位置的NaN则保持不变。
解决此类问题的关键在于巧妙地构建两个辅助布尔掩码,分别从前向和后向识别潜在的填充区域,然后通过逻辑与(AND)操作将它们组合起来。这样可以精确地定位到同时满足“在某个‘start’之后”和“在某个‘finish’之前”这两个条件的单元格,从而实现精准的条件填充。
我们将分步实现这一逻辑,以确保每一步的意图都清晰明了。
首先,创建一个基础布尔掩码,用于标识DataFrame中所有非NaN的单元格。这个掩码在后续步骤中至关重要,它能确保我们的ffill()和bfill()操作仅基于实际存在的字符串值进行传播,而不会将其他NaN视为传播源。
# m 标识所有非NaN的单元格
m = df['start_finish'].notna()
print("\n掩码 m (非NaN值):")
print(m)输出:
掩码 m (非NaN值): 0 True 1 False 2 False 3 True 4 False 5 False 6 True 7 False 8 False 9 True 10 False 11 True Name: start_finish, dtype: bool
此掩码旨在识别从“start”字符串开始并向下传播的区域。
# m1 标识从'start'开始向下传播的区域
# 只有在原始数据非NaN时才考虑'start',然后进行前向填充
m1 = df['start_finish'].eq('start').where(m).ffill()
print("\n掩码 m1 (从'start'向下传播):")
print(m1)输出:
掩码 m1 (从'start'向下传播): 0 True 1 True 2 True 3 False 4 False 5 False 6 True 7 True 8 True 9 True 10 True 11 False Name: start_finish, dtype: object
与m1类似,这个掩码旨在识别从“finish”字符串开始并向上回溯的区域。
# m2 标识从'finish'开始向上回溯的区域
# 只有在原始数据非NaN时才考虑'finish',然后进行后向填充
m2 = df['start_finish'].eq('finish').where(m).bfill()
print("\n掩码 m2 (从'finish'向上回溯):")
print(m2)输出:
掩码 m2 (从'finish'向上回溯): 0 False 1 True 2 True 3 True 4 False 5 False 6 False 7 False 8 False 9 False 10 True 11 True Name: start_finish, dtype: object
现在我们有了两个关键的布尔掩码:
通过对m1和m2进行逻辑与(&)操作,我们就能精确地识别出那些同时满足“在'start'之后”和“在'finish'之前”条件的单元格。这些正是我们想要填充的NaN值所在的位置。
# 组合掩码:同时满足 m1 和 m2 的条件
# 这会识别出位于 'start' 和 'finish' 之间的所有单元格
fill_mask = m1 & m2
print("\n组合掩码 (m1 & m2):")
print(fill_mask)
# 最后,使用布尔索引将这些位置的 'start_finish' 列值设置为 'check'
# 注意:此操作会修改所有满足 fill_mask 条件的单元格,包括原始为NaN和非NaN的。
# 但由于我们只关心填充NaN,且m1&m2只会是True在NaN处,所以结果符合预期。
df.loc[fill_mask, 'start_finish'] = 'check'
print("\n填充后的DataFrame:")
print(df)输出:
组合掩码 (m1 & m2): 0
以上就是Pandas中高效填充特定边界内NaN值的教程的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号