使用 MultiIndex 时,如何将此 Pandas 列类型保留为日期时间?

Posted

技术标签:

【中文标题】使用 MultiIndex 时,如何将此 Pandas 列类型保留为日期时间?【英文标题】:How can I keep this Pandas column type as datetime when using MultiIndex? 【发布时间】:2015-03-23 20:03:35 【问题描述】:

这太奇怪了,我真的想知道我是否只是误解了一些事情。

我有一些从日期时间值构建多索引的代码,但是在生成多索引后,类型已更改为时间戳我希望它保留日期时间。我为什么要关心?好吧,代码的另一部分以与相同日期时间略有不同的方式生成多索引,但在这种情况下,它保留了 datettime 类型 - 所以我不能在两个 DataFrame 之间使用更新,因为列不被视为相等(是的,我通过直接比较值来检查)。

关于最小代码示例:

import datetime
import pandas as pd
import numpy as np

iterables = [['bar', 'baz', 'foo', 'qux'], [datetime.date(2014, 10, 3)]]
columns = pd.MultiIndex.from_product(iterables)
df = pd.DataFrame(np.random.randn(4, 4),columns = columns)

这给出了:

>>> df.columns[0]
('bar', Timestamp('2014-10-03 00:00:00'))

请注意,日期的类型现在是时间戳,而不是日期时间。在我的代码的另一部分,它保持 datettime (这是正确的事件链,是吗?),所以现在它们都引用相同的日期,但测试不相等,所以我不能应用 DataFrame.update 从一个推送数据给对方。不幸的是,这两条路径都有很强的数据驱动理由,为什么它们应该按照它们的方式完成。

想到什么变通方法或解决方案?还是我错过了一些明显的东西并且整个前提很愚蠢(我不会在这里以某种方式打折这种可能性 - 我很惊讶日期时间测试不等于时间戳)?有没有一种简单的方法可以进入并更改多索引的 second level 类型以将它们改回日期时间?

编辑:差点忘了:pandas 版本 0.15.2

【问题讨论】:

df.columns.levels[1][0].to_datetime() 会将时间戳转换回日期时间。我无法立即将其应用于整个索引级别。列表理解会起作用,但我想它不是很pandas to_datetime() 返回一个datetime,但它不会修改调用者。 unutbu,感谢您的进一步解释,这很有意义。 【参考方案1】:

在构造一个MultiIndex,values get changed into Categoricals

Categoricalsdatetimes automatically get converted to Timestamps:

In [287]: pd.Categorical([datetime.date(2014, 10, 3)])[0]
Out[287]: Timestamp('2014-10-03 00:00:00')

但是Categorical of an Index does not:

In [288]: pd.Categorical(pd.Index([datetime.date(2014, 10, 3)]))[0]
Out[288]: datetime.date(2014, 10, 3)

因此,

import datetime
import pandas as pd

iterables = [['bar', 'baz', 'foo', 'qux'], pd.Index([datetime.date(2014, 10, 3)])]
columns = pd.MultiIndex.from_product(iterables)
df = pd.DataFrame(np.random.randn(4, 4),columns=columns)
print(df.columns[0])

产量

('bar', datetime.date(2014, 10, 3))

注意,我知道更改 DataFrame 的 MultiIndex 的最简单方法是重新分配一个新的 MultiIndex。因此,如果df 已经有一个带时间戳的 MultiIndex,要将 MultiIndex 转换为日期时间,请使用:

iterables = [['bar', 'baz', 'foo', 'qux'], pd.Index([datetime.date(2014, 10, 3)])]
columns = pd.MultiIndex.from_product(iterables)
df.columns = columns

【讨论】:

unutbu,你真了不起。就像我的数据回来了,一切正常!我整天都在研究它,只是在研究 categoricals.py 但可能还需要几个小时才能解决这个问题。非常感谢!这不是我第一次使用您的解决方案。

以上是关于使用 MultiIndex 时,如何将此 Pandas 列类型保留为日期时间?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MultiIndex 时如何在 Pandas 中使用转换器

在使用pandas MultiIndex时,如何基于索引值进行插值?

合并pandas DataFrames时如何保留列MultiIndex值

尝试从 python 数据帧创建多级标头-尝试 Multiindex.from_product() [重复]

如何使用日期索引和多级列进行切片 (MultiIndex)

如何使用 MultiIndex 重新索引?