Увеличьте год массива datetime без использования цикла for

У меня есть массив numpy с длинным списком дат и времени. Мне было интересно, есть ли способ добавить год ко всем значениям массива сразу без использования цикла for? например. Используя какой-то модуль numpy или datetime?

>>> import datetime
>>> import numpy as np

>>> dts.shape
(64580,)

>>> dts[:5]
array([datetime.date(2000, 1, 15), datetime.date(2000, 1, 15),
       datetime.date(2000, 1, 15), datetime.date(2000, 1, 15),
       datetime.date(2000, 1, 15)], dtype=object)

>>> new_dts = somemodule.somefunctionforaddingyearorsomething(dts, year=1)
>>> new_dts
array([datetime.date(2001, 1, 15), datetime.date(2001, 1, 15),
       datetime.date(2001, 1, 15), datetime.date(2001, 1, 15),
       datetime.date(2001, 1, 15)], dtype=object)

Примечание. День каждой даты всегда устанавливается равным 15 дню, поскольку даты представляют собой среднемесячные данные.

Я реализовал это с помощью цикла for, однако это может быть медленным в вычислительном отношении.

Код для этого здесь:

def add_year_to_Datelist(dl):

dts = dl.dates.copy()
for idx, date in enumerate(dts):
    dts[idx] = date.replace(year=date.year + 1)

dl.set_dates(dts)
return dl

Ваше здоровье


person Max Collier    schedule 04.01.2019    source источник


Ответы (2)


NumPy не поддерживает «1 год» в качестве дельты времени, так как это может быть 365 или 366 дней. Если вы хотите использовать Pandas, вы можете использовать pd.to_datetime с pd.DateOffset, что делает поддерживают смещения на основе года:

import datetime, numpy as np, pandas as pd

dts = np.array([datetime.date(2000, 1, 15), datetime.date(2000, 1, 15),
                datetime.date(2000, 1, 15), datetime.date(2000, 1, 15),
                datetime.date(2000, 1, 15)], dtype=object)

dts = (pd.to_datetime(dts) + pd.DateOffset(years=1)).values.astype('datetime64[D]')

# array(['2001-01-15', '2001-01-15', '2001-01-15', '2001-01-15',
#        '2001-01-15'], dtype='datetime64[D]')

С помощью NumPy вы можете добавить фиксированное количество дней после преобразования массива object dtype в np.datetime64:

dts = dts.astype(np.datetime64) + np.timedelta64(365, 'D')

# array(['2001-01-14', '2001-01-14', '2001-01-14', '2001-01-14',
#        '2001-01-14'], dtype='datetime64[D]')

Обратите внимание на однодневное несоответствие между двумя результатами.

person jpp    schedule 04.01.2019
comment
Ваш ответ панд работает отлично! Хотя я попробовал первый ответ и заметил, что для любого високосного года данные будут неверными. то есть месяцы январь/февраль имеют дневное значение 14, тогда как другие месяцы имеют дневное значение 15.. - person Max Collier; 04.01.2019
comment
@MaxCollier, Да, именно с этим проблема с использованием 365 дней исправлена. Насколько мне известно, нет собственного решения NumPy. - person jpp; 04.01.2019

Ускорить работу при использовании цикла for довольно сложно. Однако использование map переносит вычисления в C и может значительно ускорить процесс.

Попробуй это:

def add_year(dl, add=1):
    """Return new list with year increased by specified amount."""
    dts = list(map(lambda date: date.replace(year = date.year + add), dl.dates.copy()))
    return dts

Не уверен, как получить список numpy, потому что я еще не работал с numpy (я знаю, жалко ...), но вы знаете, да: D

person GeeTransit    schedule 04.01.2019