Hinzufügen np.timedelta64(1, 'Y')
zu einer Reihe von dtype datetime64[ns]
nicht funktioniert, weil ein Jahr auf eine feste Anzahl von Nanosekunden nicht entspricht. Manchmal ist ein Jahr 365 Tage, manchmal 366 Tage, manchmal gibt es sogar eine zusätzliche Schaltsekunde. (Beachten Sie zusätzliche Schaltsekunden, wie die, die auf 2015.06.30 23:59:60 trat nicht als NumPy datetime64s darstellbaren.)
Der einfachste Weg, ich weiß, ein Jahr zu einem NumPy datetime64[ns]
Array hinzufügen ist es in Bestandteile zu brechen, wie Jahre, Monate und Tage, auf integer-Arrays die Berechnung tun, und dann die datetime64 Array neu zusammenstellen:
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)
Ausbeuten
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]')
Trotz erscheinen, so zu sein viel Code, es ist tatsächlich schneller als ein DateOff hinzuzufügen Set von 1 Jahr:
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
Natürlich pd.tseries.offsets bietet eine ganze Palette von Offsets, die keine einfachen Gegenstück haben, wenn sie mit NumPy datetime64s arbeiten.
Ich bin erstaunt über die Geschwindigkeit und das Detail dieser Antwort! Da ich meine Daten mit Pandas lese, finde ich es einfacher, pandas DateOffset weiter zu verwenden, um Daten zu konvertieren, bevor ich meine Berechnungen mit numpy ausführe. Aber ich habe über eine Conversion nachgedacht, wie Sie es vorschlagen, also habe ich jetzt diesen Quellcode, wenn ich ihn brauche. Vielen Dank! – questiondude