将熊猫多索引切片彼此分开

Posted

技术标签:

【中文标题】将熊猫多索引切片彼此分开【英文标题】:Divide pandas multiindex slices by each other 【发布时间】:2020-10-04 22:36:30 【问题描述】:

我有一个具有四个索引级别的 pandas 多索引数据框。我正在尝试将此数据帧的一部分除以同一数据帧的另一部分。

import pandas as pd

df = pd.DataFrame(
    data="data_provider": ["prov_a", "prov_a", "prov_a", "prov_a", "prov_a", "prov_a"],
          "indicator": ["ind_a", "ind_a", "ind_a", "ind_b", "ind_b", "ind_b"],
          "unit": ["EUR", "EUR", "EUR", "EUR", "EUR", "EUR"],
          "year": ["2017", "2018","2019", "2017","2018","2019"],
          "country1": [1, 2, 3, 2, 4, 6],
          "country2": [4, 5, 6, 40, 50, 60]
)

df = df.set_index(["data_provider", "indicator", "unit", "year"], drop=True)

print(df.loc[(slice(None), ["ind_a"]), :] / df.loc[(slice(None), ["ind_b"]), :])

虽然单个切片产生df 的有效切片,但这个简单的除法会导致所有的 NaN。如果我要删除第一个索引级别并执行相同的切片和除法操作,我会得到正确的结果。但是,indicator 索引级别随后将被删除,这是有道理的。

df1.droplevel(0)
print(df.loc["ind_a", :] / df.loc["ind_b", :])

最后,我想将除法的结果附加到现有的df 数据框。我需要分配多索引的前两个级别。类似于data_provider="prov_a"indicator="ind_c"。我该怎么做?

【问题讨论】:

【参考方案1】:

问题的根源是除法的两边都有第一值 在 MultiIndex 的第 1 级。

所以如果你把这个级别的索引去掉,然后进行除法:

res = df.loc[(slice(None), ["ind_a"]), :].droplevel([1]) / \
    df.loc[(slice(None), ["ind_b"]), :].droplevel([1])

你会得到正确的结果。

要将此结果附加到源 DataFrame,请运行:

res2 = pd.concat([res], keys=['ind_c'], names=['indicator']).swaplevel(0,1)
df = pd.concat([df, res2])

结果是:

                                   country1  country2
data_provider indicator unit year                    
prov_a        ind_a     EUR  2017       1.0       4.0
                             2018       2.0       5.0
                             2019       3.0       6.0
              ind_b     EUR  2017       2.0      40.0
                             2018       4.0      50.0
                             2019       6.0      60.0
              ind_c     EUR  2017       0.5       0.1
                             2018       0.5       0.1
                             2019       0.5       0.1

【讨论】:

【参考方案2】:

我会使用 pd.IndexSliceto_numpy 从除数中去除索引,因此,pandas 不会强制数据对齐以除数据帧的相同形状部分:

import pandas as pd
df = pd.DataFrame(
    data="data_provider": ["prov_a", "prov_a", "prov_a", "prov_a", "prov_a", "prov_a"],
          "indicator": ["ind_a", "ind_a", "ind_a", "ind_b", "ind_b", "ind_b"],
          "unit": ["EUR", "EUR", "EUR", "EUR", "EUR", "EUR"],
          "year": ["2017", "2018","2019", "2017","2018","2019"],
          "country1": [1, 2, 3, 2, 4, 6],
          "country2": [4, 5, 6, 40, 50, 60]
)
df = df.set_index(["data_provider", "indicator", "unit", "year"], drop=True)

indx = pd.IndexSlice
df_new = (df.loc[indx[:, 'ind_a'], :].div(df.loc[indx[:, 'ind_b'], :].to_numpy())
            .rename(index='ind_a':'ind_c'))
df_out = pd.concat([df,df_new])
print(df_out)

输出:

                                   country1  country2
data_provider indicator unit year                    
prov_a        ind_a     EUR  2017       1.0       4.0
                             2018       2.0       5.0
                             2019       3.0       6.0
              ind_b     EUR  2017       2.0      40.0
                             2018       4.0      50.0
                             2019       6.0      60.0
              ind_c     EUR  2017       0.5       0.1
                             2018       0.5       0.1
                             2019       0.5       0.1

【讨论】:

以上是关于将熊猫多索引切片彼此分开的主要内容,如果未能解决你的问题,请参考以下文章

切片具有大列表的多索引熊猫数据框

熊猫如何切片多索引数据框?

熊猫:切片多索引与许多索引

将值从一个数据帧切片复制到另一个:使用“IndexSlice”的多索引熊猫数据帧的切片是不是总是一致地排序?

对唯一顺序索引的多索引熊猫数据框进行切片和赋值

具有重复值的 Python 多索引切片