如何使用 MultiIndex 重新索引?

Posted

技术标签:

【中文标题】如何使用 MultiIndex 重新索引?【英文标题】:How to reindex with MultiIndex? 【发布时间】:2021-01-31 14:36:41 【问题描述】:

我有一个这样的 DataFrame:

import pandas as pd
df = pd.DataFrame.from_dict('var1': 0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  10: 0.0,
 'var2': 0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  10: 0.0,
 'var3': 0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  10: 0.0,
 'var4': 0: 0.0,
  1: 0.0,
  2: 0.0,
  3: 0.0,
  4: 0.0,
  6: 0.0,
  7: 0.0,
  8: 0.0,
  10: 0.0)

我想填补缺失的索引,所以我首先使用了.reindex

df.reindex(np.arange(1, 11))

我得到了:

    var1    var2    var3    var4
1   0.0     0.0     0.0     0.0
2   0.0     0.0     0.0     0.0
3   0.0     0.0     0.0     0.0
4   0.0     0.0     0.0     0.0
5   NaN     NaN     NaN     NaN
6   0.0     0.0     0.0     0.0
7   0.0     0.0     0.0     0.0
8   0.0     0.0     0.0     0.0
9   NaN     NaN     NaN     NaN
10  0.0     0.0     0.0     0.0

但是,我需要跟踪多个索引,当我尝试构建 MultiIndex 并将其传递给 .reindex 时,它并没有像我预期的那样工作:

    df.reindex(pd.MultiIndex.from_product([["A"], np.arange(1, 11)]))

        var1    var2    var3    var4
A   1   NaN     NaN     NaN     NaN
    2   NaN     NaN     NaN     NaN
    3   NaN     NaN     NaN     NaN
    4   NaN     NaN     NaN     NaN
    5   NaN     NaN     NaN     NaN
    6   NaN     NaN     NaN     NaN
    7   NaN     NaN     NaN     NaN
    8   NaN     NaN     NaN     NaN
    9   NaN     NaN     NaN     NaN
   10   NaN     NaN     NaN     NaN

我真的不明白这里发生了什么,.reindex 的文档对我来说不是很清楚。有人可以就此提出建议并告诉我为什么不能将 MultiIndex 传递给 .reindex 或者我做错了什么?

@编辑:

@jazrael 在我们从 1 级到 2 级 MultiIndex 时提供了一个很好的解决方案。但是,如果我们想从 2-level MultiIndex 重新索引到 3-level MultiIndex,该怎么办?

例如:

df.index = pd.MultiIndex.from_arrays([np.repeat([1, 2], [4, 5]), df.index])

        var1    var2    var3    var4
1   0   0.0     0.0     0.0     0.0
    1   0.0     0.0     0.0     0.0
    2   0.0     0.0     0.0     0.0
    3   0.0     0.0     0.0     0.0
2   4   0.0     0.0     0.0     0.0
    6   0.0     0.0     0.0     0.0
    7   0.0     0.0     0.0     0.0
    8   0.0     0.0     0.0     0.0
   10   0.0     0.0     0.0     0.0

我想得到:

            var1    var2    var3    var4
A   1   0   0.0     0.0     0.0     0.0
        1   0.0     0.0     0.0     0.0
        2   0.0     0.0     0.0     0.0
        3   0.0     0.0     0.0     0.0
    2   4   0.0     0.0     0.0     0.0
        5   NaN     NaN     NaN     NaN
        6   0.0     0.0     0.0     0.0
        7   0.0     0.0     0.0     0.0
        8   0.0     0.0     0.0     0.0
        9   NaN     NaN     NaN     NaN
       10   0.0     0.0     0.0     0.0

【问题讨论】:

这个额外级别的重新索引的最终用途是什么?是因为你要连接几个数据框吗? @Ben.T 是的。我需要跟踪当前处理的子集以便稍后将它们连接起来。 如果您使用pd.concat 进行连接,您可以使用字典或keys 参数来跟踪您放入连接的Frame or Series 对象。 【参考方案1】:

因为想要简单地使用reindex,而不是MultiIndex 索引是必要的设置level=1 以匹配新MultiIndex 的第二级:

df = df.reindex(pd.MultiIndex.from_product([["A"], np.arange(1, 11)]), level=1)
print (df)
      var1  var2  var3  var4
A 1    0.0   0.0   0.0   0.0
  2    0.0   0.0   0.0   0.0
  3    0.0   0.0   0.0   0.0
  4    0.0   0.0   0.0   0.0
  5    NaN   NaN   NaN   NaN
  6    0.0   0.0   0.0   0.0
  7    0.0   0.0   0.0   0.0
  8    0.0   0.0   0.0   0.0
  9    NaN   NaN   NaN   NaN
  10   0.0   0.0   0.0   0.0
  

【讨论】:

谢谢!你能详细解释一下吗?我真的不明白这个解决方案是如何工作的。据我了解,我的 MultiIndex 已经和np.arange(1, 11)的长度一样了 @Xaume - 在数据框中是由数字创建的索引,新传递的 MultiIndex 由第一级的A创建,第二级的数字。所以需要原始索引和新 MultiIndex 的第二级之间的匹配数字,这意味着需要 reindex 表示通过 level=1 使用第二级进行 reindex。 @Xaume - 也许是为了更好地理解文档中的帮助示例? DataFrame.reindex ? @Xaume - 如果还有什么不清楚的地方告诉我,我会试着解释更多。 不幸的是,文档没有级别属性的用例,我仍在努力理解它是如何工作的。尤其是现在,当我遇到我的df 有 2 个级别的 MultiIndex 并且我试图用 3 级 MultiIndex 重新索引它时 - level=1 不再起作用(以及类似level=[1,2] 的东西)。请参阅我的 @edit 示例。【参考方案2】:

您可以创建具有额外级别的新索引并执行显式 DataFrame 连接以获得所需的内容。

df.index = pd.MultiIndex.from_arrays([np.repeat([1, 2], [4, 5]), df.index], names=["key1", "key2"])
# If df's index is already created, do df.rename_axis(["key1", "key2"], inplace=True)

new_index = pd.MultiIndex.from_arrays([['A']*11, np.repeat([1, 2], [4, 7]), range(11)],
                                       names=["new_key", *df.index.names])
output = pd.DataFrame([], index=new_index).join(df, on=df.index.names)  # Join on overlapped index levels based on names

输出:

                   var1  var2  var3  var4
new_key key1 key2                        
A       1    0      0.0   0.0   0.0   0.0
             1      0.0   0.0   0.0   0.0
             2      0.0   0.0   0.0   0.0
             3      0.0   0.0   0.0   0.0
        2    4      0.0   0.0   0.0   0.0
             5      NaN   NaN   NaN   NaN
             6      0.0   0.0   0.0   0.0
             7      0.0   0.0   0.0   0.0
             8      0.0   0.0   0.0   0.0
             9      NaN   NaN   NaN   NaN
             10     0.0   0.0   0.0   0.0

【讨论】:

以上是关于如何使用 MultiIndex 重新索引?的主要内容,如果未能解决你的问题,请参考以下文章

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

pandas - 如何使用 MultiIndex 在 DataFrame 的深层检索最小值索引

如何使用基于整数位置的索引访问 MultiIndex 数据帧中的行

重新索引 MultiIndex 数据帧的特定级别

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

Pandas Multiindex 系列级别重新索引