Подтвердить что ты не робот

Получить год, месяц или день с numpy datetime64

У меня есть массив типа datetime64:

dates = np.datetime64(['2010-10-17', '2011-05-13', "2012-01-15"])

Есть ли лучший способ, чем цикл через каждый элемент, чтобы получить np.array лет:

years = f(dates)
#output:
array([2010, 2011, 2012], dtype=int8) #or dtype = string

Я использую stable numpy version 1.6.2.

4b9b3361

Ответ 1

Поскольку datetime нестабильно в numpy, я бы использовал pandas для этого:

In [52]: import pandas as pd

In [53]: dates = pd.DatetimeIndex(['2010-10-17', '2011-05-13', "2012-01-15"])

In [54]: dates.year
Out[54]: array([2010, 2011, 2012], dtype=int32)

Pandas использует numpy datetime внутри, но, похоже, избегает нехватки, которая имеет значение numpy до сих пор.

Ответ 2

Я обнаружил, что следующие трюки дают между увеличением 2x и 4x по сравнению с описанным выше способом pandas (т.е. pd.DatetimeIndex(dates).year и т.д.). Скорость [dt.year for dt in dates.astype(object)] Я считаю похожей на метод pandas. Также эти трюки могут быть применены непосредственно к ndarrays любой формы (2D, 3D и т.д.).

dates = np.arange(np.datetime64('2000-01-01'), np.datetime64('2010-01-01'))
years = dates.astype('datetime64[Y]').astype(int) + 1970
months = dates.astype('datetime64[M]').astype(int) % 12 + 1
days = dates - dates.astype('datetime64[M]') + 1

Ответ 3

Должен быть более простой способ сделать это, но, в зависимости от того, что вы пытаетесь сделать, лучшим способом может быть преобразование в обычный объект datetime Python:

datetime64Obj = np.datetime64('2002-07-04T02:55:41-0700')
print datetime64Obj.astype(object).year
# 2002
print datetime64Obj.astype(object).day
# 4

Судя по комментариям ниже, это работает только в Python 2.7.x и Python 3. 6+

Ответ 4

Если вы обновляетесь до numpy 1.7 (где datetime все еще отображается как экспериментальный), то следующее должно работать.

dates/np.timedelta64(1,'Y')

Ответ 5

Использование numpy версии 1.10.4 и pandas версии 0.17.1,

dates = np.array(['2010-10-17', '2011-05-13', '2012-01-15'], dtype=np.datetime64)
pd.to_datetime(dates).year

Я получаю то, что вы ищете:

array([2010, 2011, 2012], dtype=int32)

Ответ 6

Нет никакого прямого способа сделать это, к сожалению, но есть несколько косвенных способов:

[dt.year for dt in dates.astype(object)]

или

[datetime.datetime.strptime(repr(d), "%Y-%m-%d %H:%M:%S").year for d in dates]

оба вдохновлены примерами здесь.

Обе из них работают для меня на Numpy 1.6.1. Возможно, вам понадобится быть более осторожным со вторым, так как функция rep() для datetime64 может иметь долю до запятой после десятичной точки.

Ответ 7

Ответ Anon отлично работает для меня, но мне просто нужно изменить инструкцию для days

от

days = dates - dates.astype('datetime64[M]') + 1

в

days = dates.astype('datetime64[D]') - dates.astype('datetime64[M]') + 1

Ответ 8

Другая возможность:

np.datetime64(dates,'Y') - returns - numpy.datetime64('2010')

или

np.datetime64(dates,'Y').astype(int)+1970 - returns - 2010

но работает только со скалярными значениями, не будет принимать массив

Ответ 9

Вот как я это делаю.

import numpy as np

def dt2cal(dt):
    """
    Convert array of datetime64 to a calendar array of year, month, day, hour,
    minute, seconds, microsecond with these quantites indexed on the last axis.

    Parameters
    ----------
    dt : datetime64 array (...)
        numpy.ndarray of datetimes of arbitrary shape

    Returns
    -------
    cal : uint32 array (..., 7)
        calendar array with last axis representing year, month, day, hour,
        minute, second, microsecond
    """

    # allocate output 
    out = np.empty(dt.shape + (7,), dtype="u4")
    # decompose calendar floors
    Y, M, D, h, m, s = [dt.astype(f"M8[{x}]") for x in "YMDhms"]
    out[..., 0] = Y + 1970 # Gregorian Year
    out[..., 1] = (M - Y) + 1 # month
    out[..., 2] = (D - M) + 1 # dat
    out[..., 3] = (dt - D).astype("m8[h]") # hour
    out[..., 4] = (dt - h).astype("m8[m]") # minute
    out[..., 5] = (dt - m).astype("m8[s]") # second
    out[..., 6] = (dt - s).astype("m8[us]") # microsecond
    return out

Он векторизован по произвольным входным измерениям, он быстрый, интуитивно понятный, работает на numpy v1.15.4, не использует панд.