首页 > 解决方案 > 为什么 Pandas Series div 方法会使结果 Series 丢失多索引类型

问题描述

我的问题涉及代数运算后多索引熊猫系列中的索引类型保留。在下面的示例中,我将特别考虑该div方法。​</p>

案例 1:2 级多索引工作正常

我必须处理具有多索引的 Pandas 系列,其中每个级别都是CategoricalIndex这样的:

import pandas as pd

V0_cat_idx = pd.CategoricalIndex([10, 20, 30],
                                 ​categories=[10, 20, 30],
                                 ​ordered=True,
                                 ​name="V0")
V1_cat_idx = pd.CategoricalIndex(["B", "A"],
                                 ​categories=["B", "A"],
                                 ​ordered=True,
                                 ​name="V1")

cat_midx = pd.MultiIndex.from_product([V0_cat_idx, V1_cat_idx])

myseries = pd.Series(range(6), index=cat_midx)
print(myseries)
V0  V1
10  B     0
   ​ A     1
20  B     2
   ​ A     3
30  B     4
    ​A     5

现在我想将我的 Serie 标准化如下:

norm = myseries.sum(level=["V1"])

myseries_norm = myseries.div(norm)
print(myseries_norm)
V0  V1
10  B     0.000000
    ​A     0.111111
20  B     0.333333
   ​ A     0.333333
30  B     0.666667
    ​A     0.555556

在这种情况下,一切似乎都很好,因为myseries_norm具有与myseries. 该div方法保留了CategoricalIndex多索引的每个级别的类型。

(myseries_norm.index.levels[0] == V0_cat_idx).all() # True
(myseries_norm.index.levels[1] == V1_cat_idx).all() # True

案例 2:3 级多索引失败

现在让我们添加一个级别并执行相同类型的标准化,如下所示:

V2_cat_idx = pd.CategoricalIndex(["X", "Y"],
                                ​categories=["X", "Y"],
                                ​name="V2")
cat_midx_2 = pd.MultiIndex.from_product([V0_cat_idx, V1_cat_idx, V2_cat_idx])

myseries_2 = pd.Series(range(12), index=cat_midx_2)

# Normalization
norm_2 = myseries_2.sum(level=["V1", "V2"])
myseries_norm_2 = myseries_2.div(norm_2)

如果我们现在查看 的索引类型myseries_norm_2,我们注意到我们丢失了CategoricalIndex类型。但是,div 操作是在两个兼容CategoricalIndex类型的 multiindex 的 Series 上进行的。

print(myseries_norm_2.index.levels[0]) # -> NOK CategoricalIndex expected
Index(['A', 'B'], dtype='object', name='V1')
print(myseries_norm_2.index.levels[1]) # -> NOK CategoricalIndex expected
Index(['X', 'Y'], dtype='object', name='V2')
print(myseries_norm_2.index.levels[2]) # -> OK
CategoricalIndex([10, 20, 30], categories=[10, 20, 30], ordered=True, dtype='category', name='V0') 

我们还可以注意到,由于级别 V0 现在是最右边的级别,因此执行了级别置换。

那么,如果知道案例 1 的行为似乎更一致,我们如何解释div案例 1 和案例 2 之间方法的不同行为呢?

案例 3:选择得当的 3 级多索引似乎有效……

现在让我们尝试myseries_3在最右边创建一个 V0 级别的系列,如下所示:

cat_midx_3 = pd.MultiIndex.from_product(
        [V1_cat_idx, V2_cat_idx, V0_cat_idx])

myseries_3 = pd.Series(range(12), index=cat_midx_3)
norm_3 = myseries_3.sum(level=["V1", "V2"])

myseries_norm_3 = myseries_3.div(norm_3)

在这种情况下,它可以工作。为每个CategoricalIndex级别保留类型:

print(myseries_3.index.levels[0])
CategoricalIndex(['B', 'A'], categories=['B', 'A'], ordered=True, dtype='category', name='V1')
print(myseries_3.index.levels[1])
CategoricalIndex(['X', 'Y'], categories=['X', 'Y'], ordered=False, dtype='category', name='V2')
print(myseries_3.index.levels[2])
CategoricalIndex([10, 20, 30], categories=[10, 20, 30], ordered=True, dtype='category', name='V0')

正如你可以想象的那样,我对所有这些不同的行为有点困惑......

这是一个错误,这是故意的吗?

任何帮助将非常感激。

提前致谢。

标签: pythonpandasseriesmulti-index

解决方案


推荐阅读