【问题标题】:Expand a pandas multi-index with N new levels for each index?为每个索引扩展 N 个新级别的 pandas 多索引?
【发布时间】:2014-07-15 18:19:16
【问题描述】:

我经常遇到这样的情况,即我有一个具有以下级别的 pandas 多索引:

ix = pd.MultiIndex.from_tuples(((1, 2),
                                (1, 3),
                                (2, 2),
                                (2, 5)), names=['hi', 'there'])
a = pd.DataFrame([0]*4, index=ix, columns=['foo'])

采用这种结构:

print a
          foo
hi there   
1  2      0
   3      0
2  2      0
   5      0

但是,我想扩展这些索引,例如每个级别 3 个新索引。所以我想添加另一个索引,使最终产品看起来像这样:

                  foo
hi there newix     
1  2     1        0
         2        0
   3     1        0
         2        0
2  2     1        0
         2        0
   5     1        0
         2        0

我想不出使用“from_product”之类的明显方法来做到这一点。我想我可以通过迭代前两行来手动构造元组,但这似乎很麻烦。有没有比我想象的更优雅的方法来实现这一点?

编辑:理想情况下,这将是其他的东西,比如说:

newixs = []
for ix in a.index:
    for i in range(5):
        nix = list(ix) + [i]
        newixs.append(nix)

这可行(使用 from_tuples 制作 pandas 多索引),但对我来说似乎很老套:P

【问题讨论】:

    标签: python pandas scipy


    【解决方案1】:

    我会先使用 concat 创建一个更大的 DataFrame:

    In [11]: res = pd.concat([a, a])
    
    In [12]: res
    Out[12]: 
              foo
    hi there     
    1  2        0
       3        0
    2  2        0
       5        0
    1  2        0
       3        0
    2  2        0
       5        0
    

    我认为追加新索引的最简单方法是添加新列,然后添加set_index

    In [13]: res['newix'] = np.repeat([1, 2], len(a))
    
    In [14]: res
    Out[14]: 
              foo  newix
    hi there            
    1  2        0      1
       3        0      1
    2  2        0      1
       5        0      1
    1  2        0      2
       3        0      2
    2  2        0      2
       5        0      2
    
    In [15]: res.set_index('newix', append=True)
    Out[15]: 
                    foo
    hi there newix     
    1  2     1        0
       3     1        0
    2  2     1        0
       5     1        0
    1  2     2        0
       3     2        0
    2  2     2        0
       5     2        0
    

    这基本上是你想要的(如果需要,你可以res.sort_index())。

    【讨论】:

      【解决方案2】:

      您可以简单地对目标索引 ix3 使用重新索引(使用隐式广播):

      ix3 = pd.MultiIndex.from_tuples(
          [(1, 2, 1), (1, 2, 2),
           (1, 3, 1), (1, 3, 2),
           (2, 2, 1), (2, 2, 2),
           (2, 5, 1), (2, 5, 2)],
          names=['hi', 'there', 'newix'])
      
      a.reindex(ix3)    
                         foo
      hi  there   newix   
      1   2       1      0
                  2      0
          3       1      0
                  2      0
      2   2       1      0
                  2      0
          5       1      0
                  2      0
      

      【讨论】:

        猜你喜欢
        • 2015-01-07
        • 2021-12-21
        • 2015-12-13
        • 2022-01-26
        • 2018-11-27
        • 2018-07-09
        • 2016-12-01
        • 2016-12-27
        相关资源
        最近更新 更多