0

我正在编写一个应用程序,它使用 pandas(版本 0.10.1)将底层数据模型存储为(3 级)MultiIndex'ed DataFrame。模型是线谱,索引的顶层是原子跃迁。

一个简单的数据框可能如下所示:

                               Pos     Sigma       Ampl  Line center Identifier
H-alpha-6697.6 30-30 Comp2  -3.600  0.774000  33.058000       6699.5          b
                     Comp3   3.538  2.153000  28.054000       6699.5          c
                     Contin    NaN       NaN   0.000000          NaN        NaN
                     Comp4   1.384  0.921000  37.504000       6699.5          d
                     Comp1  -2.124  1.977000  69.166000       6699.5          a
               31-31 Comp2  -3.292  0.884603  49.813423       6699.5          b
                     Comp3   3.600  2.299000  19.999000       6699.5          c
                     Contin    NaN       NaN   0.000000          NaN        NaN
                     Comp4   1.692  1.009000  22.222000       6699.5          d
                     Comp1  -1.262  2.534000  68.002000       6699.5          a

在某些时候,我需要能够使用 H-alpha 作为模板创建不同的过渡,例如 H-beta。理想情况下,我会这样做df.ix['H-beta-wavelength'] = df.ix['H-alpha-6697.6'],但这是不可能的。因此,我尝试按照以下示例进行操作:Prepend a level to a pandas MultiIndex

但是,上面的示例需要.names设置多索引级别的 ,以便对它们重新排序。并且names属性是在初始化数据框时设置的,但是在构建它的过程中,我非常依赖 set_values() 方法,这样做会破坏names属性 - 或者更确切地说将它们设置为[None, None, None].

例子:

In [68]: df
Out[68]: 
                                  Pos  Sigma     Ampl  Line center Identifier
Transition     Rows  Component                                               
Center: 6699.5 26-26 Comp2     -3.846  0.657  15.2740       6699.5          b
                     Comp3      2.924  1.449  31.3930       6699.5          c
                     Contin       NaN    NaN   0.0000          NaN        NaN
                     Comp4      8.030  1.009   7.0831       6699.5          d
                     Comp1     -1.816  2.153  50.2750       6699.5          a

In [69]: df.set_value(('Center: 5044.3', '26-26', 'Comp1'), 'Sigma', 2.457)
Out[69]: 
                               Pos  Sigma     Ampl  Line center Identifier
Center: 6699.5 26-26 Comp2  -3.846  0.657  15.2740       6699.5          b
                     Comp3   2.924  1.449  31.3930       6699.5          c
                     Contin    NaN    NaN   0.0000          NaN        NaN
                     Comp4   8.030  1.009   7.0831       6699.5          d
                     Comp1  -1.816  2.153  50.2750       6699.5          a
Center: 5044.3 26-26 Comp1     NaN  2.457      NaN          NaN        NaN

当然,这使得使用名称重新排序多索引的级别变得非常困难。有没有办法避免这种情况,每次我跑完之后都蛮力设置名称set_values()

编辑:更简单、可重复的示例。

这是一个 iPython 会话,它index.names用一个更简单的示例重新创建了问题。它还表明它可能是一个超出 的错误index.names,因为它似乎将index.lexsort_depth3 更改为 0。提示中缺少的数字只是数据框的不必要视图。我相信必须像我在下面所做的那样选择已经存在的二级和/或三级索引才能复制它。

In [4]: idx = pd.MultiIndex.from_arrays(
            [['Hans']*4 + ['Grethe']*4, ['1', '1', '2', '2']*2, ['a', 'b']*4], 
            names=['Name', 'Number', 'Letter'])

In [5]: df = pd.DataFrame(
            random.random((8, 3)), 
            columns=['one', 'two','three'], 
            index=idx)


In [6]: df
Out[6]: 
                           one       two     three
Name   Number Letter                              
Hans   1      a       0.803566  0.434574  0.805976
              b       0.655322  0.208469  0.989559
       2      a       0.893952  0.380358  0.173764
              b       0.822446  0.673894  0.676573
Grethe 1      a       0.202641  0.387263  0.405296
              b       0.646733  0.086953  0.882114
       2      a       0.358458  0.147107  0.769586
              b       0.183782  0.477863  0.601098

# To rule out another possible source of problems:
In [9]: df.unstack().drop(('Grethe', '1')).stack()
Out[9]: 
                           one       two     three
Name   Number Letter                              
Grethe 2      a       0.358458  0.147107  0.769586
              b       0.183782  0.477863  0.601098
Hans   1      a       0.803566  0.434574  0.805976
              b       0.655322  0.208469  0.989559
       2      a       0.893952  0.380358  0.173764
              b       0.822446  0.673894  0.676573

In [10]: df.set_value(('Frans', '2', 'b'), 'one', 23.)
Out[10]: 
                  one       two     three
Hans   1 a   0.803566  0.434574  0.805976
         b   0.655322  0.208469  0.989559
       2 a   0.893952  0.380358  0.173764
         b   0.822446  0.673894  0.676573
Grethe 1 a   0.202641  0.387263  0.405296
         b   0.646733  0.086953  0.882114
       2 a   0.358458  0.147107  0.769586
         b   0.183782  0.477863  0.601098
Frans  2 b  23.000000       NaN       NaN

In [11]: df = df.sortlevel(level='Name')

In [13]: df.index.lexsort_depth
Out[13]: 3

In [14]: df.set_value(('Frans', '2', 'b'), 'one', 23.).index.lexsort_depth
Out[14]: 0
4

2 回答 2

1

您的索引需要排序!请参阅此处的文档:http: //pandas.pydata.org/pandas-docs/dev/indexing.html#the-need-for-sortedness这些食谱可能会有所帮助http://pandas.pydata.org/pandas-docs/ dev/cookbook.html 这也是 0.10.1

这是一个排序的框架

In [26]: index = pd.MultiIndex.from_arrays([['a', 'a', 'b', 'b'], [1, 2, 1, 2]],
              names=['first', 'second'])

In [27]: df = pd.DataFrame(np.random.rand(len(index)), index=index,columns=['A'])

In [7]: df.index.lexsort_depth
Out[7]: 2

In [28]: df.set_value(('a',1),'A',1)
Out[28]: 
                     A
first second          
a     1       1.000000
      2       0.136456
b     1       0.712612
      2       0.818473

如果我按第二级排序(所以它未排序)

In [29]: df2 = df.sortlevel(level='second')

# this is not sorted! (well it is, just not lexsorted)
In [10]: df2.index.lexsort_depth
Out[10]: 0

In [30]: df2.set_value(('b','1'),'A',2)
Out[30]: 
            A
a 1  1.000000
b 1  0.712612
a 2  0.136456
b 2  0.818473
  1  2.000000
于 2013-03-25T20:33:31.940 回答
0

所以根据安迪海登的说法,这是names熊猫的一个错误。希望很快会有修复。

在此之前,我认为最好的方法是执行以下操作:

tmp = df.ix['ExistingTransition'].copy()
tmp['Transition'] = 'NewTransition'
tmp = tmp.set_index('Transition', append=True)
tmp.index = tmp.index.reorder_levels([2, 0, 1])
# ...Do whatever else needs to be done to this before applying as template...
df = df.append(tmp)

...那,或者确保names在每次运行后重新创建属性set_values(),然后通过问题中链接的示例进行操作。

于 2013-03-25T20:45:36.597 回答