为何将pandas Timestamp列转为object类型会变为datetime且丢失时区?
Pandas Timestamp转object类型后变为datetime且丢失时区的问题分析
先来看一个具体的场景:我们创建一个包含Timestamp类型列和整数列的DataFrame:
import pandas as pd df = pd.DataFrame({'A':[(pd.Timestamp.utcnow()+pd.Timedelta(hours=1)) for i in range(3)], 'B':[i for i in range(3)]}) df
运行后得到的结果是:
A B 0 2018-05-24 09:57:32.263331+00:00 0 1 2018-05-24 09:57:32.264331+00:00 1 2 2018-05-24 09:57:32.264331+00:00 2
此时检查A列的元素类型,确认都是Pandas的Timestamp对象:
set((type(t) for t in df['A']))
输出:
{pandas._libs.tslib.Timestamp}
接下来我们手动把所有列转为dtype='object'类型(这么做是为了模拟合并类型不兼容列时自动转object的场景,方便观察内容变化):
df = pd.DataFrame({c:pd.Series(df[c].values, index=df.index, dtype='object') for c in df.columns}) df
转换后的结果显示A列的时区信息消失了:
A B 0 2018-05-24 09:57:32.263331 0 1 2018-05-24 09:57:32.264331 1 2 2018-05-24 09:57:32.264331 2
再次检查A列的元素类型,发现全部变成了Python原生的datetime.datetime对象:
set((type(t) for t in df['A']))
输出:
{datetime.datetime}
这时候就会产生疑问:为何pandas不保留自身类型?
更严重的是,原本的时区信息完全丢失了,现在的datetime都是无时区感知的:
(df['A'].iloc[0], df['A'].iloc[0].tzinfo)
输出:
(datetime.datetime(2018, 5, 24, 9, 57, 32, 263331), None)
环境说明:Pandas 0.22、Python 3.6.3。
其实这个问题的根源不在Pandas本身,而是在numpy上——正如@user2285236指出的那样:当对Timestamp序列调用.values(也就是df[c].values)时,会提取出底层的numpy数组,但numpy并不支持带时区的datetime类型,所以这个数组实际上是无时区的datetime数组。而原本的时区信息其实是存储在Pandas的Series对象中的,并非每个Timestamp元素单独携带(或者说numpy层面无法保留),所以通过这种方式重建列时,时区信息就丢失了,同时Pandas的Timestamp类型也被转换成了Python原生的datetime类型。
内容的提问来源于stack exchange,提问作者Ymareth
相关产品推荐
相关产品推荐

