为何显式设置Series为自动推断的datetime64[ns, UTC] dtype会触发TypeError?
关于显式指定带时区datetime dtype触发TypeError的问题解析
我来帮你拆解这个看似费解的问题,先从场景重现说起:
当我们用列表推导创建包含UTC时间戳的Series时,Pandas能自动推断出正确的datetime64[ns, UTC] dtype:
import pandas as pd pd.Series([pd.Timestamp.utcnow() for v in range(5)])
输出结果:
0 2018-05-16 08:24:29.673274+00:00 1 2018-05-16 08:24:29.673274+00:00 2 2018-05-16 08:24:29.673274+00:00 3 2018-05-16 08:24:29.673274+00:00 4 2018-05-16 08:24:29.673274+00:00 dtype: datetime64[ns, UTC]
但如果尝试显式指定这个dtype——不管是用字符串形式,还是直接传入已有同类型Series的dtype属性——都会报错TypeError: data type not understood:
# 字符串指定dtype的错误写法 pd.Series([pd.Timestamp.utcnow() for v in range(5)], dtype='datetime64[ns, UTC]') # 直接传入dtype对象的错误写法(旧版本Pandas) existing_series = pd.Series([pd.Timestamp.utcnow() for v in range(5)]) pd.Series([pd.Timestamp.utcnow() for v in range(5)], dtype=existing_series.dtype)
为什么会出现这个问题?
核心原因是Pandas的带时区datetime dtype并非原生numpy类型:
- 原生numpy不支持带时区的
datetime64格式,datetime64[ns, UTC]是Pandas自定义的扩展dtype(属于pandas.DatetimeTZDtype类),不是标准的numpy dtype字符串。 - 当你用字符串
'datetime64[ns, UTC]'指定dtype时,Pandas会先尝试交给numpy解析,numpy无法识别带时区的后缀,直接抛出错误。 - 早期版本的Pandas在创建Series时,对扩展dtype的直接传入支持不完善,即使你传入正确的
DatetimeTZDtype对象也会报错(新版本已修复,但仍建议用标准方式指定)。
正确的解决办法
如果你需要显式指定带时区的dtype,应该使用Pandas提供的DatetimeTZDtype对象来定义,而不是字符串:
from pandas import DatetimeTZDtype # 创建UTC时区的dtype实例 utc_dtype = DatetimeTZDtype(unit='ns', tz='UTC') # 用该dtype创建Series pd.Series([pd.Timestamp.utcnow() for v in range(5)], dtype=utc_dtype)
这样就能成功生成带有datetime64[ns, UTC] dtype的Series,和自动推断的结果完全一致。
另外,如果你是从无时区的datetime数据转换,也可以先创建普通datetime Series,再用tz_localize方法添加时区:
# 先创建无时区的datetime序列 s = pd.Series(pd.date_range('2018-05-16', periods=5)) # 本地化到UTC时区 s_utc = s.dt.tz_localize('UTC')
小提示
在较新的Pandas版本中,只要你传入的是已经带时区的Timestamp对象列表,Pandas就能自动推断出正确的带时区dtype——除非你有强制指定dtype的特殊需求,否则优先让Pandas自动推断是最省心的方式。
内容的提问来源于stack exchange,提问作者Ymareth
相关产品推荐
相关产品推荐

