Python numpy:无法将 datetime64[ns] 转换为 datetime64[D](与 Numba 一起使用)
Posted
技术标签:
【中文标题】Python numpy:无法将 datetime64[ns] 转换为 datetime64[D](与 Numba 一起使用)【英文标题】:Python numpy: cannot convert datetime64[ns] to datetime64[D] (to use with Numba) 【发布时间】:2015-11-02 06:33:44 【问题描述】:我想将一个日期时间数组传递给一个 Numba 函数(它不能被矢量化,否则会很慢)。我了解 Numba 支持 numpy.datetime64。但是,它似乎支持 datetime64[D](天精度)但不支持 datetime64[ns](毫秒精度)(我很难学到这一点:它记录了吗?)。
我尝试将 datetime64[ns] 转换为 datetime64[D],但似乎找不到方法!有什么想法吗?
我用下面的最少代码总结了我的问题。如果你运行testdf(mydates)
,也就是 datetime64[D],它可以正常工作。如果您运行 testdf(dates_input)
,即 datetime64[ns],则不会。请注意,此示例只是将日期传递给 Numba 函数,该函数(尚未)对它们做任何事情。我尝试将 dates_input 转换为 datetime64[D],但转换不起作用。在我的原始代码中,我从 SQL 表中读取到 pandas 数据帧,并且需要一列将每个日期的日期更改为 15 日。
import numba
import numpy as np
import pandas as pd
import datetime
mydates =np.array(['2010-01-01','2011-01-02']).astype('datetime64[D]')
df=pd.DataFrame()
df["rawdate"]=mydates
df["month_15"] = df["rawdate"].apply(lambda r: datetime.date( r.year, r.month,15 ) )
dates_input = df["month_15"].astype('datetime64[D]')
print dates_input.dtype # Why datetime64[ns] and not datetime64[D] ??
@numba.jit(nopython=True)
def testf(dates):
return 1
print testf(mydates)
如果我运行testdf(dates_input)
,我得到的错误是:
numba.typeinfer.TypingError: Failed at nopython (nopython frontend)
Var 'dates' unified to object: dates := pyobject
【问题讨论】:
这是一个非常有用的问题,但由于某种原因很难通过搜索找到。我在尝试对 pandas 数据使用np.busday_count
时收到了类似的错误,内容为:TypeError: Iterator operand 0 dtype could not be cast from dtype('<M8[ns]') to dtype('<M8[D]') according to the rule 'safe'
【参考方案1】:
Series.astype
将所有类似日期的对象转换为datetime64[ns]
。
要转换为datetime64[D]
,请在调用astype
之前使用values
获取一个NumPy数组:
dates_input = df["month_15"].values.astype('datetime64[D]')
请注意,NDFrame(例如 Series 和 DataFrame)只能将类似日期时间的对象保存为 dtype datetime64[ns]
的对象。所有类似日期时间的自动转换为通用 dtype 简化了后续日期计算。但这使得在 DataFrame 列中存储 datetime64[s]
对象成为不可能。 Pandas 核心开发者,Jeff Reback explains,
“我们不允许直接转换,因为它太复杂了,无法在内部保留除 datetime64[ns] 以外的任何内容(根本没有必要)。”
还要注意,即使 df['month_15'].astype('datetime64[D]')
具有 dtype datetime64[ns]
:
In [29]: df['month_15'].astype('datetime64[D]').dtype
Out[29]: dtype('<M8[ns]')
当您遍历系列中的项目时,您会得到 pandas Timestamps
,而不是 datetime64[ns]
s。
In [28]: df['month_15'].astype('datetime64[D]').tolist()
Out[28]: [Timestamp('2010-01-15 00:00:00'), Timestamp('2011-01-15 00:00:00')]
因此,尚不清楚 Numba 是否真的与 datetime64[ns]
有问题,它可能只是与 Timestamps
有问题。抱歉,我无法检查 - 我没有安装 Numba。
不过,尝试一下可能对你有用
testf(df['month_15'].astype('datetime64[D]').values)
因为 df['month_15'].astype('datetime64[D]').values
确实是一个 dtype datetime64[ns]
的 NumPy 数组:
In [31]: df['month_15'].astype('datetime64[D]').values.dtype
Out[31]: dtype('<M8[ns]')
如果可行,那么您不必将所有内容都转换为 datetime64[D]
,您只需将 NumPy 数组(而不是 Pandas 系列)传递给 testf
。
【讨论】:
谢谢!不过,请问这是为什么呢?我的意思是,我想不出任何合乎逻辑的原因,为什么只有年、月和日创建的日期被转换为毫秒精度,并且除非我们调用 .values,否则无法转换回日精度。它是一个错误吗?还是我在这里错过了一个根本原因?它在任何地方都有记录吗?我对 Python 进行数据分析感到非常沮丧(是的,我知道,这只是 Python 可以做的众多事情之一,但我对其他事情不感兴趣!)确实是文档质量差,尤其是与Matlab 等商业软件包 Pandas 为您做了很多通常很方便的事情。不幸的是,有时这意味着它最终会做它认为是你想要的事情(比如将所有日期转换为 datetime64[ns]/Timestamps),而实际上你想要别的东西。我不知道这个特定问题是否记录在某个地方。 不过,这并不是真正发生的事情。在我的示例中,Pandas 不必猜测我需要什么精度(天或毫秒),因为我明确告诉 Pandas (.astype(datetime64['D'] )。这听起来更像是一个错误 在某个地方,Pandas 决定将所有类似日期的数据集中到一种常见的数据类型中:datetime64[ns]
。这样做有很多好处:它使比较和日期运算更容易。这样做的结果是 没有 dtype 的系列 datetime64[D]
。也许df['month_15'].astype('datetime64[D]')
应该引发异常,而不是默默地转换为datetime64[ns]
,但只要Pandas 保持其漏斗-一切都到日期时间64 [ns] 策略,df['month_15'].astype('datetime64[D]')
不会返回一系列dtype @987654350 @.
@Pythonistaanonymous:写完这个答案后,Pandas 的“wesm”写了一个详细的评论,其中包含一些背景故事和支持其他 datetime64 单位的问题,这里:github.com/pandas-dev/pandas/issues/7307#issuecomment-224180563 - 许多 cmets这个问题在这里是相关的。【参考方案2】:
在计算两个日期之间的工作日数时遇到同样的错误:
from pandas.tseries.offsets import MonthBegin
import numpy as np
# Calculate the beginning of the month from a given date
df['Month_Begin'] = pd.to_datetime(df['MyDateColumn'])+ MonthBegin(-1)
# Calculate # of Business Days
# Convert dates to string to prevent type error [D]
df['TS_Period_End_Date'] = df['TS_Period_End_Date'].dt.strftime('%Y-%m-%d')
df['Month_Begin'] = df['Month_Begin'].dt.strftime('%Y-%m-%d')
df['Biz_Days'] = np.busday_count(df['Month_Begin'], df['MyDateColumn']) #<-- Error if not converted into strings.
我的解决方法是使用“.dt.strftime(''%Y-%m-%d')”转换日期。它适用于我的特殊情况。
【讨论】:
以上是关于Python numpy:无法将 datetime64[ns] 转换为 datetime64[D](与 Numba 一起使用)的主要内容,如果未能解决你的问题,请参考以下文章
在 python 2.7 中将包含 datetime.timedelta 的 numpy 数组转换为秒的优雅方法
如何将 numpy datetime64 转换为 datetime [重复]