以下代码重现了我遇到的问题:
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
列会发生这种情况。 最佳答案
如果还有其他人偶然发现此问题,那确实是一个错误,相关的GitHub问题是#28323和#28337
潜在的问题是由get_indexer
的PeriodIndex
方法引起的。现在,在重新编制索引时,将使用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
,但是如果另一个索引不是PeriodIndex
,则会导致一些奇怪的行为,这是该行为的一个小例子。>>> 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
显然,这不是理想的行为,解决方案是仅在与另一个
_int64index
重新建立索引时使用PeriodIndex
,否则使用常规的PeriodIndex
。我提交了一份PR来解决此问题,希望可以尽快将其包括在内。