扩展一个pandas多索引,每个索引有N个新级别?

时间:2014-07-15 18:19:16

标签: python pandas scipy

我经常遇到这样的情况:我有一个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 multiindex),但对我来说似乎很烦人:P

2 个答案:

答案 0 :(得分: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()。)

答案 1 :(得分:0)

您可以简单地在目标索引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