web-dev-qa-db-fra.com

Création de numpy linspace hors datetime

J'écris un script qui trace des données avec des dates sur l'axe des x (dans matplotlib). Je dois créer un numpy.linspace sur ces dates afin de créer une spline par la suite. Est-il possible de faire ça?

Ce que j'ai essayé

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)

Il jette cette erreur:

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

J'ai également essayé de convertir datetime en np.datetime64, mais cela ne fonctionne pas aussi bien:

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

Erreur:

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

Avez-vous envisagé d'utiliser pandas? En utilisant une approche de cette question possible en double , vous pouvez utiliser np.linspace de la manière suivante

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)

Pour obtenir un np.array de la série temporelle linéaire

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]')
11
lanery

Autant que je sache, np.linspace ne supporte pas les objets datetime. Mais peut-être pouvons-nous créer notre propre fonction qui la simule approximativement:

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

Cela devrait vous donner un np.array avec des dates allant de start à end en étapes steps (sans compter la date de fin, elles peuvent être facilement modifiées).

6
user1337

À partir des pandas 0.23, vous pouvez utiliser date_range :

import pandas as pd
x = pd.date_range(min(dates), max(dates), periods=500).to_pydatetime()
3
Joooeey
import numpy # 1.15   

start = numpy.datetime64('2001-01-01')
end = numpy.datetime64('2019-01-01')

# Linspace in days:

days = numpy.linspace(start.astype('f8'), end.astype('f8'), dtype='<M8[D]')

# Linspace in milliseconds

MS1D = 24 * 60 * 60 * 1000
daytimes = numpy.linspace(start.astype('f8') * MS1D, end.astype('f8') * MS1D, dtype='<M8[ms]')
1
Viktor

La dernière erreur nous dit que les objets np.datetime ne peuvent pas se multiplier. L'addition a été définie - vous pouvez ajouter n timesteps à une date et obtenir une autre date. Mais cela n’a aucun sens de multiplier une date.

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')

Ainsi, le moyen simple de générer une plage d'objets datetime consiste à ajouter une plage de pas de temps. Ici, par exemple, j'utilise des incréments de 10 secondes

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]')

L'erreur dans linspace est le résultat de la tentative de multiplier la start par 1., comme indiqué dans la pile d'erreurs complète:

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')

Malgré le commentaire, il semblerait que cela ne soit qu'une conversion d'ints en float. Quoi qu'il en soit, il n'a pas été écrit avec les objets datetime64 à l'esprit.

user89161's est la voie à suivre si vous souhaitez utiliser la syntaxe linspace, sinon vous pouvez simplement ajouter les incréments de la taille choisie à la date de début.

arange fonctionne avec ces dates:

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]')
0
hpaulj