2014-06-30 112 views
35

說你有這個多指標-ED數據幀:熊貓:按標籤獲取獨特的多指標水平值

df = pd.DataFrame({'co':['DE','DE','FR','FR'], 
        'tp':['Lake','Forest','Lake','Forest'], 
        'area':[10,20,30,40], 
        'count':[7,5,2,3]}) 
df = df.set_index(['co','tp']) 

,看起來像這樣:

  area count 
co tp 
DE Lake  10  7 
    Forest 20  5 
FR Lake  30  2 
    Forest 40  3 

我想檢索每個唯一值指數級別。這可以通過使用

df.index.levels[0] # returns ['DE', 'FR] 
df.index.levels[1] # returns ['Lake', 'Forest'] 

什麼,我會真的喜歡做的事,是解決各級他們的名字,即'co''tp'檢索這些列表來完成。我能找到的最短的兩種方式看起來像這樣:

list(set(df.index.get_level_values('co'))) # returns ['DE', 'FR'] 
df.index.levels[df.index.names.index('co')] # returns ['DE', 'FR'] 

但它們都非常優雅。有更短的路嗎?

+0

究竟你在這裏找什麼輸出? – acushner

回答

40

我想你想在一個多指標的特定級別(和級別名稱)的唯一值。我通常會做以下事情,時間有點長。

In [11]: df.index.get_level_values('co').unique() 
Out[11]: array(['DE', 'FR'], dtype=object) 
+0

謝謝,'unique()'是我的盲點...... – ojdo

+2

雖然這個唯一性信息已經明確存儲在索引中,但效率非常低,所以我的第二個選項@ojdo依然在我身上成爲最好的。使用'unique'的速度比我的數據慢上百倍*: 'timeit df.index.get_level_values(level ='co')。unique()'給出:1000循環,最好是3:** 851 * *每循環μs,而'timeit df.index.levels [df.index.names.index('co')]'給出:100000循環,最好是3:** 3.08 **每循環μs –

+10

@Robert Muil - 這樣做的問題是,如果任何行或列已被刪除,index.levels不會返回更新的內容,並且這不被視爲錯誤,因爲這不是MultiIndexes的批准使用(https://github.com/pydata/pandas/問題/ 3686)。 MultiIndex的* current *內容的有效API訪問實際上是get_level_values。對於那些習慣於單一索引唯一性的人來說,這很棘手。 –

2

如果你要反覆做電平查詢,您可以創建地圖索引級別名稱與地級唯一值:

df_level_value_map = { 
    name: level 
    for name, level in zip(df.index.names, df.index.levels) 
} 
df_level_value_map[''] 

但是,這是不以任何方式更如果您只需要執行一次查找,則可以比原始嘗試更有效(或更短)。

我真的希望有一個與像一個名字索引的方法,該方法返回這樣一本詞典(或系列):

df.index.get_level_map(levels={...}) 

凡水平參數可以在地圖限制在現有水平的一個子集。我可以沒有參數,如果它可能是一個屬性,如:

df.index.level_map 
5

另一種方法是通過調用df.index.levels[level_index]其中level_index可以從df.index.names.index(level_name)推斷找到的級別數。在上面的例子中,level_name ='co'。

@ Happy001提出的答案計算可能計算密集的獨特。

+0

這通常不起作用(例如,在切片數據框上,其中一些層未被使用) –