我正在编写一个脚本,在 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
转换为 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')
正如 @Joooeey 和 @Ehtesh Choudhury 所指出的,
pandas
现在有了 date_range
,这使得创建类似 numpy.linspace
的时间序列更加简单。
t = pd.date_range(
start='2022-03-10',
end='2022-03-15',
periods=5
)
如果将此时间序列作为
numpy
数组很重要,只需
>>> t.values
array(['2022-03-10T00:00:00.000000000', '2022-03-11T06:00:00.000000000',
'2022-03-12T12:00:00.000000000', '2022-03-13T18:00:00.000000000',
'2022-03-15T00:00:00.000000000'], dtype='datetime64[ns]')
您考虑过使用
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]')
从 pandas 0.23 开始,您可以使用 date_range:
import pandas as pd
x = pd.date_range(min(dates), max(dates), periods=500).to_pydatetime()
据我所知,np.linspace 不支持日期时间对象。但也许我们可以制作自己的函数来粗略地模拟它:
def date_linspace(start, end, steps):
delta = (end - start) / steps
increments = range(0, steps) * np.array([delta]*steps)
return start + increments
这将为您提供一个 np.array,其日期从
start
到 end
,步骤为 steps
(不包括结束日期,可以轻松修改)。
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]')
最后一个错误告诉我们
np.datetime
物体不能繁殖。加法已定义 - 您可以将 n
时间步添加到一个日期并获得另一个日期。但乘以日期没有任何意义。
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')
因此,生成一系列日期时间对象的简单方法是添加时间步长范围。例如,我在这里使用 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
乘以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')
尽管有评论,它看起来只是将整数转换为浮点数。不管怎样,它并不是为了
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]')