0

パンダ(バージョン0.10.1)を使用して、基になるデータモデルを(3レベルの)MultiIndex'edDataFrameとして格納するアプリケーションを作成しています。モデルは線スペクトルであり、インデックスの最上位は原子遷移です。

単純なデータフレームは次のようになります。

                               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-αをテンプレートとして使用して、別の遷移、たとえばH-βを作成できるようにする必要があります。私は理想的にはのようなものでこれを行うでしょうdf.ix['H-beta-wavelength'] = df.ix['H-alpha-6697.6']が、これは不可能です。代わりに、次の例に従ってみました。pandasMultiIndexの前にレベルを追加します

ただし、上記の例.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()か?

編集:より単純で再現可能な例。

index.namesこれは、やや単純な例で問題を再現するiPythonセッションです。index.namesまた、3から0に変更されているように見えるため、を超えるバグである可能性があることも示していindex.lexsort_depthます。プロンプトに数字が表示されないのは、データフレームの不要なビューです。私は、それを再現するために、以下で行ったように、すでに存在する二次および/または三次インデックスを選択する必要があると信じています。

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

そして、私が2番目のレベルで並べ替えると(つまり、並べ替えられていない)

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

Andy Haydenによると、これは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 に答える