我正在使用cx_oracle从数据库中获取日期。我想将获取的数据放入pandas数据帧中。我的问题是日期被转换为我绝对不需要的numpy.datetime64
个对象。
我想将它们作为datetime.date对象。我已经看到了dt.date
方法,但它仍然给出了numpy datetypes。
答案 0 :(得分:4)
编辑:看起来使用pandas 0.21.0或更新版本,在DataFrame中保存python datetime.date
是没有问题的。 date-like
列不会自动转换为datetime64[ns]
dtype。
import numpy as np
import pandas as pd
import datetime as DT
print(pd.__version__)
# 0.21.0.dev+25.g50e95e0
dates = [DT.date(2017,1,1)+DT.timedelta(days=2*i) for i in range(3)]
df = pd.DataFrame({'dates': dates, 'foo': np.arange(len(dates))})
print(all([isinstance(item, DT.date) for item in df['dates']]))
# True
df['dates'] = (df['dates'] + pd.Timedelta(days=1))
print(all([isinstance(item, DT.date) for item in df['dates']]))
# True
对于旧版本的Pandas:
有一种方法可以防止Pandas DataFrame自动转换
通过分配一个附加值(如a),将日期值设置为datetime64[ns]
空字符串与列不是日期。在DataFrame之后
形成后,您可以删除非日期值:
import pandas as pd
import datetime as DT
dates = [DT.date(2017,1,1)+DT.timedelta(days=i) for i in range(10)]
df = pd.DataFrame({'dates':['']+dates})
df = df.iloc[1:]
print(all([isinstance(item, DT.date) for item in df['dates']]))
# True
显然,将这种shenanigan编程为严格的代码感觉完全错误,因为我们颠覆了开发人员的意图。
使用datetime64[ns]
对datetime.dates
的列表或对象数组也有计算速度优势。
此外,如果df[col]
有dtype datetime64[ns]
,那么df[col].dt.date.values
会返回一个对象NumPy的python datetime.date
数组:
import pandas as pd
import datetime as DT
dates = [DT.datetime(2017,1,1)+DT.timedelta(days=2*i) for i in range(3)]
df = pd.DataFrame({'dates': dates})
print(repr(df['dates'].dt.date.values))
# array([datetime.date(2017, 1, 1), datetime.date(2017, 1, 3),
# datetime.date(2017, 1, 5)], dtype=object)
因此,您可以将列保持为datetime64[ns]
并使用df[col].dt.date.values
在必要时获取datetime.date
,从而享受两全其美。
另一方面,datetime64[ns]
和Python datetime.date
具有不同的可表示日期范围。
datetime64[ns]
可以代表1678 AD
to 2262 AD
的日期时间。datetime.date
可以表示从DT.date(0,1,1)
到DT.date(9999,1,1)
的日期。如果您要使用datetime.date
而不是datetime64[ns]
s的原因是为了克服有限范围的可表示日期,那么可能a better alternative is to use a pd.PeriodIndex
:
import pandas as pd
import datetime as DT
dates = [DT.date(2017,1,1)+DT.timedelta(days=2*i) for i in range(10)]
df = pd.DataFrame({'dates':pd.PeriodIndex(dates, freq='D')})
print(df)
# dates
# 0 2017-01-01
# 1 2017-01-03
# 2 2017-01-05
# 3 2017-01-07
# 4 2017-01-09
# 5 2017-01-11
# 6 2017-01-13
# 7 2017-01-15
# 8 2017-01-17
# 9 2017-01-19