有没有办法在不将 dtype 更改为对象的情况下将 NaT 附加到带有时区的 pandas 日期时间?
Posted
技术标签:
【中文标题】有没有办法在不将 dtype 更改为对象的情况下将 NaT 附加到带有时区的 pandas 日期时间?【英文标题】:Is there a way to append NaT to a pandas datetime with timezone without changing dtype to object? 【发布时间】:2019-08-13 20:09:16 【问题描述】:我的 DataFrame 中有一个 dtype 列:datetime64[ns, UTC]。当我在该列中附加一个带有 None 或 NaT 的行时,该列的 dtype 更改为“object”。这不会发生在 dtype: datetime64[ns] 的列上。
这是一个演示:
# Test pandas with datetime columns
import pandas as pd
from datetime import datetime, timezone
df = pd.DataFrame(['D': datetime.utcnow()])
df_wtz = pd.DataFrame(['D': datetime.now().astimezone(timezone.utc)])
df_None = pd.DataFrame(['D': None])
# Note that the tz below is ignored even though specified
df_Nat = pd.DataFrame(['D': pd.Timestamp(None,tz=timezone.utc)])
print('df:\n', df['D'])
print('df_wtz:\n', df_wtz['D'])
print('df_None:\n', df_None['D'])
print('df_Nat:\n', df_Nat['D'])
print('df append df_None:\n', df.append(df_None, ignore_index=True, sort=False)['D'])
print('df append df_Nat:\n', df.append(df_Nat, ignore_index=True, sort=False)['D'])
print('df_wtz append df_None:\n', df_wtz.append(df_None, ignore_index=True, sort=False)['D'])
print('df_wtz append df_Nat:\n', df_wtz.append(df_Nat, ignore_index=True, sort=False)['D'])
这是输出:
df:
0 2019-08-13 19:58:18.811492
Name: D, dtype: datetime64[ns]
df_wtz:
0 2019-08-13 19:58:18.811968+00:00
Name: D, **dtype: datetime64[ns, UTC]**
df_None:
0 None
Name: D, dtype: object
df_Nat:
0 NaT
Name: D, dtype: datetime64[ns]
df append df_None:
0 2019-08-13 19:58:18.811492
1 NaT
Name: D, dtype: datetime64[ns]
df append df_Nat:
0 2019-08-13 19:58:18.811492
1 NaT
Name: D, dtype: datetime64[ns]
df_wtz append df_None:
0 2019-08-13 19:58:18.811968+00:00
1 None
Name: D, dtype: object
df_wtz append df_Nat:
0 2019-08-13 19:58:18.811968+00:00
1 NaT
Name: D, dtype: object
我曾期望在将 None 或 NaT 附加到 datetime64[ns, UTC] 列的情况下保留列类型,但事实并非如此。这是预期的行为还是会被视为错误?
【问题讨论】:
【参考方案1】:您可以通过这种方式将 NaT 放在 dtype datetime64[ns, UTC]
的列中:
In [380]: df_Nat = pd.DataFrame('D': pd.to_datetime([None], utc=True)); df_Nat
Out[380]:
D
0 NaT
In [381]: df_Nat.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1 entries, 0 to 0
Data columns (total 1 columns):
D 0 non-null datetime64[ns, UTC]
dtypes: datetime64[ns, UTC](1)
memory usage: 88.0 bytes
现在将df_Nat
附加到df_wtz
会保留数据类型:
import pandas as pd
import datetime as DT
utc = DT.timezone.utc
now = DT.datetime.now()
df_wtz = pd.DataFrame(['D': now.astimezone(utc)])
df_Nat = pd.DataFrame('D': pd.to_datetime([None], utc=True))
# df_Nat = pd.DataFrame('D':pd.Series(pd.NaT, dtype='datetime64[ns, UTC]')) # also works
print('df_wtz append df_Nat:\n', df_wtz.append(df_Nat, ignore_index=True, sort=False)['D'])
产量
df_wtz append df_Nat:
0 2019-08-13 20:28:15.928023+00:00
1 NaT
Name: D, dtype: datetime64[ns, UTC]
NaT 本身不支持时区:
In [383]: pd.Timestamp(None) is pd.Timestamp(None, tz=utc)
Out[383]: True
所以pd.DataFrame(['D': pd.Timestamp(None,tz=utc)])
不会生成具有时区感知 dtype 的列。
由于不可能让 DataFrame 从 NaT 本身推断出可识别时区的 dtype,
我们需要构建一个已经具有正确时区感知 dtype 的容器(例如 Series 或 DatetimeIndex)。这就是pd.to_datetime([None], utc=True)
所做的:
In [385]: pd.to_datetime([None], utc=True)
Out[385]: DatetimeIndex(['NaT'], dtype='datetime64[ns, UTC]', freq=None)
【讨论】:
谢谢 - 这对我有用。我仍然很遗憾添加 None 会修改列类型...以上是关于有没有办法在不将 dtype 更改为对象的情况下将 NaT 附加到带有时区的 pandas 日期时间?的主要内容,如果未能解决你的问题,请参考以下文章
我们如何在不将 ViewController 对象推入其中的情况下将对象分配给 `UINavigationController`。
如何在不将 LocalDateTime 字段转换为扩展的 json 对象的情况下将 java 对象转换为简单的 json 字符串?
如何在不将 csv 保存到磁盘的情况下将 csv 格式的数据从内存发送到数据库?
如何在不覆盖 ModelForm 中的字段定义的情况下将 ManyToManyField 小部件更改为 CheckboxSelectMultiple