2013-07-29 62 views
22

代碼示例:如何查詢大熊貓多指標索引列值

In [171]: A = np.array([1.1, 1.1, 3.3, 3.3, 5.5, 6.6]) 

In [172]: B = np.array([111, 222, 222, 333, 333, 777]) 

In [173]: C = randint(10, 99, 6) 

In [174]: df = pd.DataFrame(zip(A, B, C), columns=['A', 'B', 'C']) 

In [175]: df.set_index(['A', 'B'], inplace=True) 

In [176]: df 
Out[176]: 
      C 
A B  
1.1 111 20 
    222 31 
3.3 222 24 
    333 65 
5.5 333 22 
6.6 777 74 

現在,我想檢索值:
Q1:在區間[3.3,6.6] - 預期的返回值: 3.3,5.5,6.6]或[3.3,3.5,5.6,6.6],如果不是,則爲[3.3,5.5]或[3.3,3.3,5.5]。
Q2:在範圍[2.0,4.0] - 預期的返回值:[3.3]或[3.3,3.3]

同任何其它多指標尺寸,例如B值:
Q3 :在範圍[111,500]以重複,如在範圍內的數據的行數 - 預期的返回值:[111,222,222,333,333]

更正式:

讓我們假定T是列A,B和C的表格。表格e包括n行。表單元是數字,例如A,B和C整數。讓我們創建一個表T的DataFrame,讓我們命名爲DF。讓我們設置DF的列A和B索引(沒有重複,即沒有單獨的列A和B作爲索引,並且作爲數據分開),即在這種情況下的A和B MultiIndex

問題:

  1. 如何寫上的索引的查詢,例如,查詢索引A(或B),例如在標籤間隔[120.0,540.0]?標籤120.0和540.0存在。我必須澄清,我只對索引列表感興趣,作爲對查詢的迴應!
  2. 如何相同,但在標籤120.0和540.0不存在的情況下,但標籤的值低於120,高於120且低於540或高於540?
  3. 如果Q1和Q2的答案是唯一的索引值,現在與索引範圍中的數據行數相同,但具有重複性。

我知道答案,在沒有索引的列的情況下,上述的問題,但在指標的情況下,經過長期的研究在web和實驗的大熊貓功能後,我沒有成功。唯一的方法(無需額外編程)我現在看到除了索引之外,還有一個A和B的副本作爲數據列。

+2

爲什麼不直接向我們展示您的數據框代碼?你的解釋很難理解... – sjakobi

+1

添加的代碼@simon –

+0

感謝您使這個問題更清晰。但我不知道如何實現你想要做的事...... – sjakobi

回答

41

要查詢DF多指標值,例如其中(A> 1.7)和(B < 666)

In [536]: result_df = df.loc[(df.index.get_level_values('A') > 1.7) & (df.index.get_level_values('B') < 666)] 

In [537]: result_df 
Out[537]: 
      C 
A B  
3.3 222 43 
    333 59 
5.5 333 56 

因此,獲得例如「A」索引值,如果仍需要:

In [538]: result_df.index.get_level_values('A') 
Out[538]: Index([3.3, 3.3, 5.5], dtype=object) 

的問題是,在大的數據由索引選擇由10%差於排序規則的行選擇幀的性能。在重複的工作中,循環,延遲積累。見例如:

In [558]: df = store.select(STORE_EXTENT_BURSTS_DF_KEY) 

In [559]: len(df) 
Out[559]: 12857 

In [560]: df.sort(inplace=True) 

In [561]: df_without_index = df.reset_index() 

In [562]: %timeit df.loc[(df.index.get_level_values('END_TIME') > 358200) & (df.index.get_level_values('START_TIME') < 361680)] 
1000 loops, best of 3: 562 µs per loop 

In [563]: %timeit df_without_index[(df_without_index.END_TIME > 358200) & (df_without_index.START_TIME < 361680)] 
1000 loops, best of 3: 507 µs per loop 
8

對於'浮動'索引,你總是希望將它用作列而不是直接索引操作。無論端點是否存在,這些都將起作用。

In [11]: df 
Out[11]: 
      C 
A B  
1.1 111 81 
    222 45 
3.3 222 98 
    333 13 
5.5 333 89 
6.6 777 98 

In [12]: x = df.reset_index() 

Q1

In [13]: x.loc[(x.A>=3.3)&(x.A<=6.6)] 
Out[13]: 
    A B C 
2 3.3 222 98 
3 3.3 333 13 
4 5.5 333 89 
5 6.6 777 98 

Q2

In [14]: x.loc[(x.A>=2.0)&(x.A<=4.0)] 
Out[14]: 
    A B C 
2 3.3 222 98 
3 3.3 333 13 

Q3

In [15]: x.loc[(x.B>=111.0)&(x.B<=500.0)] 
Out[15]: 
    A B C 
0 1.1 111 81 
1 1.1 222 45 
2 3.3 222 98 
3 3.3 333 13 
4 5.5 333 89 

如果你想在後面的索引,只設置它們。這是一項便宜的操作。

In [16]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B']) 
Out[16]: 
      C 
A B  
1.1 111 81 
    222 45 
3.3 222 98 
    333 13 
5.5 333 89 

如果你真的想要的實際指數值

In [5]: x.loc[(x.B>=111.0)&(x.B<=500.0)].set_index(['A','B']).index 
Out[5]: 
MultiIndex 
[(1.1, 111), (1.1, 222), (3.3, 222), (3.3, 333), (5.5, 333)] 
+0

謝謝@Jeff,但在這種情況下,最好將上述索引列的重複保存爲常規數據列。但事實是,就我而言,最初的整個表格非常大,並且存儲在HDFStore中,我每次處理通過查詢接收到的不同數據幀。並用冗餘數據向HDFStore添加兩個附加列 - 浪費空間。困境... –

+0

實際上,如果它在一家商店,那麼我根本就不會存儲索引;將要查詢的列存儲爲* data_columns *(將其隱含索引),請參閱:http://pandas.pydata.org/pandas-docs/dev/io.html#query-via-data-columns,indexes(的數據幀)已經作爲列存儲在表中,所以你可以直接查詢它們 – Jeff

+0

沒有那麼好的性能。用例是循環查詢HDFStore用於sum子表;在每個以上的迭代中處理其他循環中的子表。如果我將在內部循環中使用完全索引的HDFStore查詢而不是DataFrame,那麼對於每個子循環查詢(當前使用IPython%timeit進行檢查),處理時間將會增加超過100次。 –

11

爲了更好的可讀性,我們可以簡單地使用the query() Method,避免冗長df.index.get_level_values()reset_index/​​來來回回。

這裏是目標DataFrame

In [12]: df                  
Out[12]:                  
      C                  
A B                   
1.1 111 68                  
    222 40                  
3.3 222 20                  
    333 11                  
5.5 333 80                  
6.6 777 51 

回答爲Q1A在範圍[3.3, 6.6]):

In [13]: df.query('3.3 <= A <= 6.6') # for closed interval      
Out[13]:                  
      C                  
A B                   
3.3 222 20                  
    333 11                  
5.5 333 80                  
6.6 777 51                  

In [14]: df.query('3.3 < A < 6.6') # for open interval       
Out[14]:                  
      C                  
A B                   
5.5 333 80 

,當然可以玩弄<, <=, >, >=任何包容。


同樣,答案(在範圍[2.0, 4.0]A)Q2

In [15]: df.query('2.0 <= A <= 4.0')           
Out[15]:                  
      C                 
A B                  
3.3 222 20                 
    333 11 

回答爲Q3B在範圍[111, 500]):

In [16]: df.query('111 <= B <= 500')           
Out[16]:                  
      C                 
A B                  
1.1 111 68                 
    222 40                 
3.3 222 20                 
    333 11                 
5.5 333 80 

而且,您可以COMBINE非常自然地查詢col AB

In [17]: df.query('0 < A < 4 and 150 < B < 400')        
Out[17]:                  
      C                 
A B                  
1.1 222 40                 
3.3 222 20                 
    333 11