【问题标题】:Pandas pivot_table: `margins=True` shows `NaN` with `Period` columnsPandas pivot_table:`margins=True` 显示 `NaN` 和 `Period` 列
【发布时间】:2019-09-09 11:48:24
【问题描述】:

以下代码重现了我遇到的问题:

import pandas as pd

df = pd.DataFrame(
    {
        "a": [1, 1, 2, 2],
        "b": [
            pd.Period("2019Q1"),
            pd.Period("2019Q2"),
            pd.Period("2019Q1"),
            pd.Period("2019Q2"),
        ],
        "x": 1.0,
    }
)

df.pivot_table(index="a", columns="b", values="x", margins=True)

输出:

b   2019Q1  2019Q2  All
a           
1   1.0     1.0     1.0
2   1.0     1.0     1.0
All NaN     NaN     1.0

为什么是NaN 小计?我本来期望的:

b   2019Q1  2019Q2  All
a           
1   1.0     1.0     1.0
2   1.0     1.0     1.0
All 1.0     1.0     1.0

Period 列会发生这种情况。

【问题讨论】:

标签: python pandas


【解决方案1】:

如果其他人偶然发现这个问题,那确实是一个bug,相关的GitHub问题是#28323#28337


根本问题是由PeriodIndexget_indexer 方法引起的。现在,在重新索引时,而不是使用实际的PeriodIndex,而是使用PeriodIndex_int64index。相关代码can be found here,总结如下:

if isinstance(target, PeriodIndex):
    target = target.asi8

if tolerance is not None:
    tolerance = self._convert_tolerance(tolerance, target)
return Index.get_indexer(self._int64index, target, method, limit, tolerance)

如果使用另一个 PeriodIndex 重新索引,这显然可以正常工作,因为目标也转换为 int,但如果另一个索引 不是 @987654332,则会导致一些不稳定的行为@,这是行为的一个小例子。

>>> i = pd.PeriodIndex([pd.Period("2019Q1", "Q-DEC"), pd.Period("2019Q2", "Q-DEC")])
>>> j = pd.Index([pd.Period("2019Q1", "Q-DEC"), 'All'])
>>> s = pd.Series([1, 2], index=i)
>>> s
2019Q1    1
2019Q2    2
Freq: Q-DEC, dtype: int64
>>> s.reindex(j)
2019Q1   NaN
All      NaN
dtype: float64
>>> s.index._int64index
Int64Index([196, 197], dtype='int64')
>>> s.reindex([196])
196    1
dtype: int64

显然这不是我们想要的行为,解决方案是仅在使用另一个PeriodIndex 重新索引时使用_int64index,否则使用常规PeriodIndex。我提交了一个 PR 来解决这个问题,希望很快就会包括在内。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-22
    • 2018-01-14
    • 2012-10-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    相关资源
    最近更新 更多