2013-03-17 64 views
15

我有一個數據幀「DF」與(時間,股票)多指標和買入/賣出的/ etc數據列:選擇從一個數據幀的多鍵橫截面

 

          tod last  bid  ask  volume 
    time  ticker     
    2013-02-01 SPY  1600 149.70 150.14 150.17 1300 
       SLV  1600 30.44 30.38 30.43 3892 
       GLD  1600 161.20 161.19 161.21 3860 

我想選擇第二級別(級別= 1)使用多個鍵的橫截面。現在,我可以使用一個鍵,即

 

    df.xs('SPY', level=1) 

這給我一個SPY的時間序列。什麼是選擇多鍵橫截面,既SPY和GLD的,即組合截面,像最好的辦法:

 

    df.xs(['SPY', 'GLD'], level=1) 

回答

5

轉換爲一組,然後索引是直接

In [20]: df = pd.DataFrame(dict(time = pd.Timestamp('20130102'), 
           A = np.random.rand(3), 
       ticker=['SPY','SLV','GLD'])).set_index(['time','ticker']) 

In [21]: df 
Out[21]: 
          A 
time  ticker   
2013-01-02 SPY  0.347209 
      SLV  0.034832 
      GLD  0.280951 

In [22]: p = df.to_panel() 

In [23]: p 
Out[23]: 
<class 'pandas.core.panel.Panel'> 
Dimensions: 1 (items) x 1 (major_axis) x 3 (minor_axis) 
Items axis: A to A 
Major_axis axis: 2013-01-02 00:00:00 to 2013-01-02 00:00:00 
Minor_axis axis: GLD to SPY 

In [24]: p.ix[:,:,['SPY','GLD']] 
Out[24]: 
<class 'pandas.core.panel.Panel'> 
Dimensions: 1 (items) x 1 (major_axis) x 2 (minor_axis) 
Items axis: A to A 
Major_axis axis: 2013-01-02 00:00:00 to 2013-01-02 00:00:00 
Minor_axis axis: SPY to GLD 
7

我找不到比使用其他select更直接的方式:

>>> df 

     last tod 
A SPY  1 1600 
    SLV  2 1600 
    GLD  3 1600 

>>> df.select(lambda x: x[1] in ['SPY','GLD']) 

     last tod 
A SPY  1 1600 
    GLD  3 1600 
+2

不錯,這可能是最簡單的方法。我想知道它是否是最有效的,因爲爲每一行調用lambda可能會很慢,但是我不確定在當前版本 – 2013-03-19 02:56:18

+0

中有沒有更快的方法看到上面的面板解決方案?選擇是否對任何一種非平凡的框架都非常低效 – Jeff 2013-03-19 21:49:39

+1

確實面板更有意義,速度也更快。謝謝! – 2013-03-24 20:33:25

1

對於什麼是值得的,我做的以下內容:

foo = pd.DataFrame(np.random.rand(12,3), 
        index=pd.MultiIndex.from_product([['A','B','C','D'],['Green','Red','Blue']], 
                names=['Letter','Color']), 
        columns=['X','Y','Z']).sort_index() 

foo.reset_index()\ 
    .loc[foo.reset_index().Color.isin({'Green','Red'})]\ 
    .set_index(foo.index.names) 

該方法與select類似,但避免使用lambda迭代所有行。

不過,我比較這對小組的做法,它出現在面板解決方案更快(2.91毫秒指數/ LOC VS 1.48毫秒to_panel/to_frame:

foo.to_panel()[:,:,['Green','Red']].to_frame() 

時報:

In [56]: 
%%timeit 
foo.reset_index().loc[foo.reset_index().Color.isin({'Green','Red'})].set_index(foo.index.names) 
100 loops, best of 3: 2.91 ms per loop 

In [57]: 
%%timeit 
foo2 = foo.reset_index() 
foo2.loc[foo2.Color.eq('Green') | foo2.Color.eq('Red')].set_index(foo.index.names) 
100 loops, best of 3: 2.85 ms per loop 

In [58]: 
%%timeit 
foo2 = foo.reset_index() 
foo2.loc[foo2.Color.ne('Blue')].set_index(foo.index.names) 
100 loops, best of 3: 2.37 ms per loop 

In [54]: 
%%timeit 
foo.to_panel()[:,:,['Green','Red']].to_frame() 
1000 loops, best of 3: 1.18 ms per loop 

UPDATE

重溫這個話題(再次)後,我觀察到以下:

In [100]: 
%%timeit 
foo2 = pd.DataFrame({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}).transpose() 
foo2.index.names = foo.index.names 
foo2.columns.names = foo2.columns.names 
100 loops, best of 3: 1.97 ms per loop 

In [101]: 
%%timeit 
foo2 = pd.DataFrame.from_dict({k: foo.loc[k] for k in foo.index if k[1] in ['Green','Red']}, orient='index') 
foo2.index.names = foo.index.names 
foo2.columns.names = foo2.columns.names 
100 loops, best of 3: 1.82 ms per loop 

如果你不關心保留原來的秩序和層次的命名,你可以使用:

%%timeit 
pd.concat({key: foo.xs(key, axis=0, level=1) for key in ['Green','Red']}, axis=0) 
1000 loops, best of 3: 1.31 ms per loop 

如果你只是在第一級選擇:

%%timeit 
pd.concat({key: foo.loc[key] for key in ['A','B']}, axis=0, names=foo.index.names) 
1000 loops, best of 3: 1.12 ms per loop 

與:

%%timeit 
foo.to_panel()[:,['A','B'],:].to_frame() 
1000 loops, best of 3: 1.16 ms per loop 

另一個更新

如果您對示例foo的索引進行排序,以上許多時間都會改進(時間已更新以反映預先排序的索引)。然而,當指數進行排序,你可以使用user674155描述的解決方案:

%%timeit 
foo.loc[(slice(None), ['Blue','Red']),:] 
1000 loops, best of 3: 582 µs per loop 

這是最有效,最直觀的在我看來(用戶並不需要了解面板和它們是如何從創建幀)。

注意:即使索引尚未排序,動態排序foo的索引在性能上與to_panel選項的性能相當。

3

沒有與較新版本的熊貓這樣做的更好的方法:

regression_df.loc[(slice(None), ['SPY', 'GLD']), :] 

這種方法要求該指數是按字典順序排序(使用df.sort_index())。