所有结果均根据 1M 数据点计算。
赛通+np.vectorize
比原始代码快 7.2 倍
%%cython
from cpython.datetime cimport datetime
cpdef bint c_is_in_dst(datetime dt):
return dt.dst().total_seconds() != 0
%%timeit
df['isInDST'] = np.vectorize(c_is_in_dst)(df['time'].dt.tz_localize('UTC').dt.tz_convert('Australia/Victoria').dt.to_pydatetime())
每个循环 1.08 s ± 10.2 ms
np.vectorize
比原始代码快 6.5 倍
def is_in_dst(dt):
return dt.dst().total_seconds() != 0
%%timeit
df['isInDST'] = np.vectorize(is_in_dst)(df['time'].dt.tz_localize('UTC').dt.tz_convert('Australia/Victoria').dt.to_pydatetime())
每个循环 1.2 s ± 29.3 ms
基于文档 https://numpy.org/doc/stable/reference/generated/numpy.vectorize.html (The implementation is essentially a for loop
)我预计结果与列表理解相同,但它始终比列表理解好一点。
列表理解
比原代码快5.9倍
%%timeit
df['isInDST'] = [x.dst().total_seconds()!=0 for x in pd.DatetimeIndex(df['time']).tz_localize('UTC').tz_convert('Australia/Victoria')]
每个循环 1.33 秒 ± 48.4 毫秒
这一结果表明,大熊猫map
/apply
非常慢,它增加了额外的开销,可以通过使用 python for 循环来消除。
原始方法(map
在 pandas DatetimeIndex 上)
%%timeit
df['isInDST'] = pd.DatetimeIndex(df['time']).tz_localize('UTC').tz_convert('Australia/Victoria').map(lambda x : x.dst().total_seconds()!=0)
每个循环 7.82 秒 ± 84.3 毫秒
在 100 万行虚拟数据上进行测试
N = 1_000_000
df = pd.DataFrame({"time": [datetime.datetime.now().replace(hour=random.randint(0,23),minute=random.randint(0,59)) for _ in range(N)]})
另外,在 100K 和 10M 行上运行代码 - 结果与行数线性相关