另一个答案有效,但任何时候使用apply,都会使代码变慢很多。通过为系列编写快速矢量化日期时间替换,我能够获得 8.5 倍的加速。
def vec_dt_replace(series, year=None, month=None, day=None):
return pd.to_datetime(
{'year': series.dt.year if year is None else year,
'month': series.dt.month if month is None else month,
'day': series.dt.day if day is None else day})
申请:
%timeit dtseries.apply(lambda dt: dt.replace(day=1))
# 4.17 s ± 38.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
矢量化:
%timeit vec_dt_replace(dtseries, day=1)
# 491 ms ± 6.48 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
请注意,尝试将日期更改为不存在的日期可能会遇到错误,例如尝试将 2012-02-29 更改为 2013-02-29。使用pd.to_datetime 的errors 参数忽略或强制它们。
数据生成:生成具有 100 万个随机日期的系列:
import pandas as pd
import numpy as np
# Generate random dates. Modified from: https://stackoverflow.com/a/50668285
def pp(start, end, n):
start_u = start.value // 10 ** 9
end_u = end.value // 10 ** 9
return pd.Series(
(10 ** 9 * np.random.randint(start_u, end_u, n)).view('M8[ns]'))
start = pd.to_datetime('2015-01-01')
end = pd.to_datetime('2018-01-01')
dtseries = pp(start, end, 1000000)
# Remove time component
dtseries = dtseries.dt.normalize()