如何删除DataFrame中的NaN值及其两侧相邻的非NaN数据行
实现方案
核心思路是先标记需要删除的NaN区块行,再通过膨胀操作将删除范围扩展到这些行的前后各3行,最后过滤保留未标记的行即可,10万行级别的数据用向量化操作处理效率极高,不会有性能问题。
依赖导入
首先导入需要用到的库:
import pandas as pd import numpy as np from scipy.ndimage import binary_dilation
步骤1:加载数据(如果还没加载的话)
# 替换为你的文件路径 df = pd.read_csv("your_file.csv")
步骤2:标记NaN区块对应的坏行
你可以根据实际需求调整坏行的判定规则,示例规则如下:
- 如果要标记整行全为NaN的行作为坏行:
bad_row_mask = df.isna().all(axis=1)
- 如果要标记超过N列为NaN的行作为坏行(比如超过10列是NaN就算坏行):
# 阈值可自行调整 bad_row_mask = df.isna().sum(axis=1) > 10
步骤3:扩展删除范围到坏行前后各3行
用形态学膨胀操作实现范围扩展,结构元素长度为 3(前) + 1(坏行本身) +3(后)=7:
# 构造结构元素,长度对应要覆盖的行范围 structure = np.ones(7, dtype=bool) # 生成最终要删除的行掩码 to_drop_mask = binary_dilation(bad_row_mask, structure=structure)
步骤4:过滤得到最终数据
# 保留不需要删除的行 clean_df = df[~to_drop_mask].reset_index(drop=True)
参数调整说明
- 如果需要删除的前后行数不是3,修改
structure的长度即可:比如前后各删2行的话,structure = np.ones(5, dtype=bool) - 坏行的判定规则可以根据你的数据特征自由调整,只要输出布尔类型的掩码即可
- 如果不想额外引入scipy依赖,也可以用pandas的rolling方法实现等价逻辑:
# 用rolling实现同样的范围扩展效果,窗口大小7,center=True表示以当前行为中心扩展,min_periods=1表示只要窗口内有1个坏行就标记整个窗口的行 to_drop_mask = bad_row_mask.rolling(window=7, center=True, min_periods=1).max().astype(bool)
内容的提问来源于stack exchange,提问作者georgeamccarthy
相关产品推荐
相关产品推荐

