从日期时间创建 numpy linspace

Posted

技术标签:

【中文标题】从日期时间创建 numpy linspace【英文标题】:Creating numpy linspace out of datetime 【发布时间】:2016-10-24 03:55:18 【问题描述】:

我正在编写一个脚本,用 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')

【问题讨论】:

numpydatetimenp.datetime64 包装器(我认为)可能会起作用。 已经试过了,有问题 【参考方案1】:

您是否考虑过使用pandas?使用this possible duplicate question的方法,您可以通过以下方式使用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.date_range添加一个稍微简单的解决方案:t = pd.date_range('2015-07-01', '2015-08-01', periods=100)【参考方案2】:

从 pandas 0.23 开始,您可以使用 date_range:

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

【讨论】:

请注意,这会创建一个 numpy 数组,其 dtype object 包含 Python datetime 对象。要获得 dtype datetime64 的 numpy 数组,您需要使用 .to_numpy() 而不是 to_pydatetime()【参考方案3】:

据我所知,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,日期从 startendsteps 步骤中(不包括结束日期,可以轻松修改)。

【讨论】:

delta 可能不精确,加起来不精确会导致在处理小时间值时返回的结束值与传入的结束值相差很大。 包含结束日期,大致相当于 np.linspace 的endpoint=True,我添加了一个endpoint=True 参数并使用divisor = (steps-1) if endpoint else stepsdelta = (end - start) / divisor【参考方案4】:
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]')

【讨论】:

欢迎来到 ***。虽然这段代码 sn-p 可以解决问题,但包含解释确实有助于提高帖子的质量。请花点时间阅读How to Answer。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因【参考方案5】:

最后一个错误告诉我们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 对象。

如果你想使用linspace 语法,user89161's 是要走的路,否则你可以将所选大小的增量添加到开始日期。

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

【讨论】:

以上是关于从日期时间创建 numpy linspace的主要内容,如果未能解决你的问题,请参考以下文章

如何在不使用 Pandas 的情况下创建等效于 numpy.nan 的日期时间对象?

当我从 api (yfinance) 获取数据时,Numpy Array 缺少日期

numpy中linspace用法 (等差数列创建函数)

numpy.linspace()等差数列函数

在numpy(python)中将日期时间字符串转换为日期时间

用于多个开始和停止值的矢量化 NumPy linspace