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')
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]')
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).
À 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()
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]')
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]')