Добавление np.timedelta64(1, 'Y')
в массив DTYPE datetime64[ns]
не работает, потому что год не соответствует фиксированным числом наносекунд. Иногда год составляет 365 дней, иногда 366 дней, иногда даже второй прыжок. (Обратите внимание на дополнительные прыжковые секунды, например, тот, который произошел в 2015-06-30 23:59:60, не могут быть представлены как NumPy datetime64.)
Самый простой способ, который я знаю, добавить год к массиву NumPy datetime64[ns]
чтобы разбить его на составные части, такие как годы, месяцы и дни, делать вычисления на целых массивов, а затем перекомпонуйте datetime64 массив:
def year(dates):
"Return an array of the years given an array of datetime64s"
return dates.astype('M8[Y]').astype('i8') + 1970
def month(dates):
"Return an array of the months given an array of datetime64s"
return dates.astype('M8[M]').astype('i8') % 12 + 1
def day(dates):
"Return an array of the days of the month given an array of datetime64s"
return (dates - dates.astype('M8[M]'))/np.timedelta64(1, 'D') + 1
def combine64(years, months=1, days=1, weeks=None, hours=None, minutes=None,
seconds=None, milliseconds=None, microseconds=None, nanoseconds=None):
years = np.asarray(years) - 1970
months = np.asarray(months) - 1
days = np.asarray(days) - 1
types = ('<M8[Y]', '<m8[M]', '<m8[D]', '<m8[W]', '<m8[h]',
'<m8[m]', '<m8[s]', '<m8[ms]', '<m8[us]', '<m8[ns]')
vals = (years, months, days, weeks, hours, minutes, seconds,
milliseconds, microseconds, nanoseconds)
return sum(np.asarray(v, dtype=t) for t, v in zip(types, vals)
if v is not None)
# break the datetime64 array into constituent parts
years, months, days = [f(dates_np) for f in (year, month, day)]
# recompose the datetime64 array after adding 1 to the years
dates3 = combine64(years+1, months, days)
урожайности
In [185]: dates3
Out[185]:
array(['1981-01-01', '1981-01-02', '1981-01-03', ..., '2015-12-30',
'2015-12-31', '2016-01-01'], dtype='datetime64[D]')
Несмотря на появление настолько много кода, это на самом деле быстрее, чем добавление DateOff набор 1 года:
In [206]: %timeit dates + DateOffset(years=1)
1 loops, best of 3: 285 ms per loop
In [207]: %%timeit
.....: years, months, days = [f(dates_np) for f in (year, month, day)]
.....: combine64(years+1, months, days)
.....:
100 loops, best of 3: 2.65 ms per loop
Конечно, pd.tseries.offsets предлагает целый арсенал сдвигов, которые не имеют аналогов легко при работе с NumPy datetime64s.
Я поражен скоростью и деталями этого ответа! Поскольку я читал свои данные с помощью панд, мне легче просто продолжать использовать параметр DateOffset для pandas, чтобы преобразовать даты, прежде чем выполнять свои вычисления с помощью numpy. Но я подумал о том, как сделать конверсию, как вы предлагаете, поэтому теперь у меня есть исходный код, если он мне понадобится. Благодаря! – questiondude