我使用这个函数
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
- 更新**
穆斯塔法的回答是:
>> timeit.timeit(lambda: pd.Series(np.where(df.eq(0).all(), 0, len(df) - df[::-1].idxmax())), number=100)
0.8847485752776265
帕杜回答:
>> timeit.timeit(lambda: df.apply(calculate_recency_for_one_column_numpy, raw=True, axis=0), number=100)
0.8892530500888824
2条答案
按热度按时间x0fgdtte1#
您可以不将列视为
Series
对象,而将其视为numpy
数组。为此,只需在apply
方法中指定raw=True
参数。还需要稍微更改原始函数。sqougxex2#
其中是向量化的if-else,所以:
len(df)
取rsub定时比较:
和健全性检查: