如何提升DataFrame全列自定义函数apply操作的执行效率?
问题:优化DataFrame列级最近非零值逆位置计算效率
我实现了以下自定义函数,用于返回数值型pd.Series中最后一个非零值的逆位置:若最后一个值非零则返回1,若所有值均为非零则返回0:
def calculate_recency_for_one_column(column: pd.Series) -> int: """Returns the inverse position of the last non-zero value in a pd.Series of numerics. If the last value is non-zero, returns 1. If all values are non-zero, returns 0.""" non_zero_values_of_col = column[column.astype(bool)] if non_zero_values_of_col.empty: return 0 return len(column) - non_zero_values_of_col.index[-1]
我通过以下代码将该函数应用于示例DataFrame的所有列:
df = pd.DataFrame(np.random.binomial(n=1, p=0.001, size=[1000000]).reshape((1000,1000)))
df.apply(lambda column: calculate_recency_for_one_column(column),axis=0)
执行结果如下:
0 436 1 0 2 624 3 0 ... 996 155 997 715 998 442 999 163 Length: 1000, dtype: int64
功能运行正常,但由于该操作需要频繁执行,我需要更高效的替代方案。我认为calculate_recency_for_one_column()函数本身效率尚可,df.apply()存在最大优化空间。以下是原方法的基准测试结果(执行100次):
>>> timeit.timeit(lambda: df.apply(lambda column: calculate_recency_for_one_column(column),axis=0), number=100) 14.700050864834338
优化方案测试结果
更新
Mustafa提供的方案测试结果:
>>> timeit.timeit(lambda: pd.Series(np.where(df.eq(0).all(), 0, len(df) - df[::-1].idxmax())), number=100) 0.8847485752776265
padu提供的方案测试结果:
>>> timeit.timeit(lambda: df.apply(calculate_recency_for_one_column_numpy, raw=True, axis=0), number=100) 0.8892530500888824
内容的提问来源于stack exchange,提问作者Viktor
相关产品推荐
相关产品推荐

