pandas用itertuples遍历行时is_valid_na_for_dtype等NA校验耗时高如何优化?
你重写方法不生效的核心原因是:pandas内部调用is_valid_na_for_dtype的模块,大多是在你执行重写操作前,就已经将该函数导入到了自身的命名空间,你修改原模块的引用不会同步更新这些已导入的副本,因此补丁无法生效。
以下是3种可行的解决方法:
方案1:自行实现无NA校验的行遍历逻辑
既然你已经确认DataFrame完全没有NA值,可以直接绕开pandas原生itertuples的校验逻辑,自己实现兼容输出的遍历方法,性能提升最明显:
from collections import namedtuple def fast_itertuples(df, name="Pandas"): # 构造和原生itertuples一致的namedtuple结构 fields = [f"_{i}" if isinstance(col, int) else col for i, col in enumerate(df.columns)] RowTuple = namedtuple(name, fields, rename=True) # 直接读取numpy数组遍历,全程无NA校验 for row in df.to_numpy(): yield RowTuple(*row)
使用时直接替换你代码里的df.itertuples()为fast_itertuples(df)即可,输出格式和原生完全一致,没有兼容性问题。
方案2:精准覆盖itertuples调用的函数引用
如果你必须使用pandas原生的itertuples方法,可以直接修改itertuples实现所在模块导入的is_valid_na_for_dtype引用:
import pandas as pd from pandas.core.dtypes import missing # 定义mock方法,直接返回False表示无有效NA def mock_is_valid_na(*args, **kwargs): return False # 先覆盖原模块的引用 missing.is_valid_na_for_dtype = mock_is_valid_na # 再覆盖DataFrame类所在模块导入的引用,itertuples实际调用的是这个 pd.core.frame.is_valid_na_for_dtype = mock_is_valid_na
修改完成后再调用itertuples就会走你定义的mock方法,跳过所有NA校验逻辑。
方案3:统一使用无NA能力的原生dtype
如果你的DataFrame所有列都使用原生numpy dtype(例如用int64代替可空的Int64、用object存字符串代替可空string dtype),pandas的NA校验逻辑会直接识别到该类dtype不支持存储NA,直接返回False,不需要额外校验,也能大幅降低这部分的耗时。
内容的提问来源于stack exchange,提问作者Yakir Hadad
相关产品推荐
相关产品推荐

