Python numpy:无法将datetime64 [ns]转换为datetime64 [D](与Numba一起使用)

时间:2015-08-10 11:07:58

标签: python numpy pandas numba

我想将一个日期时间数组传递给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}

2 个答案:

答案 0 :(得分:27)

Series.astype会将所有类似日期的对象转换为datetime64[ns]。 要转换为datetime64[D],请在调用values之前使用astype获取NumPy数组:

dates_input = df["month_15"].values.astype('datetime64[D]')

请注意,NDFrame(例如Series和DataFrames)只能将类似日期时间的对象保存为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

答案 1 :(得分:1)

计算两个日期之间的工作日数时遇到相同的错误:

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')”转换日期。在我的特定情况下有效。