Создание numpy linspace из datetime

Я пишу сценарий, который строит некоторые данные с датами на оси x (в matplotlib). Мне нужно создать numpy.linspace из этих дат, чтобы впоследствии создать сплайн. Возможно ли это сделать?

что я пробовал:

import datetime
import numpy as np

dates = [
    datetime.datetime(2015, 7, 2, 0, 31, 41),
    datetime.datetime(2015, 7, 2, 1, 35),
    datetime.datetime(2015, 7, 2, 2, 37, 9),
    datetime.datetime(2015, 7, 2, 3, 59, 16),
    datetime.datetime(2015, 7, 2, 5, 2, 23)]

x = np.linspace(min(dates), max(dates), 500)

он выдает эту ошибку:

TypeError: unsupported operand type(s) for *: 'datetime.datetime' and 'float'

Я также попытался преобразовать datetime to np.datetime64, но это тоже не работает:

dates = [ np.datetime64(i) for i in dates ]
x = np.linspace(min(dates), max(dates), 500)

ошибка:

TypeError: ufunc multiply cannot use operands with types dtype('<M8[us]') and dtype('float64')

4 ответов


вы рассматривали возможность использования pandas? Используя подход от это возможный дубликат вопроса, вы можете использовать np.linspace следующим образом

import pandas as pd

start = pd.Timestamp('2015-07-01')
end = pd.Timestamp('2015-08-01')
t = np.linspace(start.value, end.value, 100)
t = pd.to_datetime(t)

для получения np.array линейных временных рядов

In [3]: np.asarray(t)
Out[3]: 
array(['2015-06-30T17:00:00.000000000-0700',
       '2015-07-01T00:30:54.545454592-0700',
       '2015-07-01T08:01:49.090909184-0700',
               ...
       '2015-07-31T01:58:10.909090816-0700',
       '2015-07-31T09:29:05.454545408-0700',
       '2015-07-31T17:00:00.000000000-0700'], dtype='datetime64[ns]')

насколько я знаю, np.linspace не поддерживает объекты datetime. Но, возможно, мы можем сделать нашу собственную функцию, которая грубо имитирует ее:

def date_linspace(start, end, steps):
  delta = (end - start) / steps
  increments = range(0, steps) * np.array([delta]*steps)
  return start + increments

это должно дать вам np.массив с датами, идущими от start to end на steps шаги (не включая дату окончания, можно легко изменить).


начиная с панды 0.23 вы можете использовать date_range:

import pandas as pd
x = pd.date_range(min(dates), max(dates), periods=500).to_pydatetime()

последняя ошибка говорит о том, что np.datetime объекты не могут размножаться. Добавление было определено - вы можете добавить n timesteps на дату и получить другую дату. Но нет никакого смысла умножать дату.

In [1238]: x=np.array([1000],dtype='datetime64[s]')

In [1239]: x
Out[1239]: array(['1970-01-01T00:16:40'], dtype='datetime64[s]')

In [1240]: x[0]*3
...
TypeError: ufunc multiply cannot use operands with types dtype('<M8[s]') and dtype('int32')

таким образом, простой способ создания диапазона объектов datetime-добавить диапазон временных шагов. Вот, например, я через 10 секунд

In [1241]: x[0]+np.arange(0,60,10)
Out[1241]: 
array(['1970-01-01T00:16:40', '1970-01-01T00:16:50', '1970-01-01T00:17:00',
       '1970-01-01T00:17:10', '1970-01-01T00:17:20', '1970-01-01T00:17:30'], dtype='datetime64[s]')

ошибка linspace является результатом его попытки умножить start by 1., как видно из полного стека ошибок:

In [1244]: np.linspace(x[0],x[-1],10)
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1244-6e50603c0c4e> in <module>()
----> 1 np.linspace(x[0],x[-1],10)

/usr/lib/python3/dist-packages/numpy/core/function_base.py in linspace(start, stop, num, endpoint, retstep, dtype)
     88 
     89     # Convert float/complex array scalars to float, gh-3504
---> 90     start = start * 1.
     91     stop = stop * 1.
     92 

TypeError: ufunc multiply cannot use operands with types dtype('<M8[s]') and dtype('float64')

несмотря на комментарий, похоже, что это просто преобразование ints в float. В любом случае это не было написано с datetime64 объекты в уме.

user89161's это путь, если вы хотите использовать linspace синтаксис, в противном случае вы можете просто добавить увеличивает размер выбранного к дате начала.

arange работает с этими датами:

In [1256]: np.arange(x[0],x[0]+60,10)
Out[1256]: 
array(['1970-01-01T00:16:40', '1970-01-01T00:16:50', '1970-01-01T00:17:00',
       '1970-01-01T00:17:10', '1970-01-01T00:17:20', '1970-01-01T00:17:30'], dtype='datetime64[s]')