2013-06-21 77 views
13

我有一個通過groupby操作創建的多索引DataFrame。我試圖做一個複合排序使用幾個級別的索引,但我似乎無法找到一個排序功能,做我所需要的。在熊貓中進行多指標排序

初始數據集看起來是這樣的(各種產品的日常銷售數):

  Date Manufacturer Product Name Product Launch Date Sales 
0 2013-01-01  Apple   iPod   2001-10-23  12 
1 2013-01-01  Apple   iPad   2010-04-03  13 
2 2013-01-01  Samsung  Galaxy   2009-04-27  14 
3 2013-01-01  Samsung Galaxy Tab   2010-09-02  15 
4 2013-01-02  Apple   iPod   2001-10-23  22 
5 2013-01-02  Apple   iPad   2010-04-03  17 
6 2013-01-02  Samsung  Galaxy   2009-04-27  10 
7 2013-01-02  Samsung Galaxy Tab   2010-09-02  7 

我使用GROUPBY的日期範圍內獲得一筆:

> grouped = df.groupby(['Manufacturer', 'Product Name', 'Product Launch Date']).sum() 
               Sales 
Manufacturer Product Name Product Launch Date  
Apple  iPad   2010-04-03    30 
      iPod   2001-10-23    34 
Samsung  Galaxy  2009-04-27    24 
      Galaxy Tab 2010-09-02    22 

到目前爲止好!

現在我想做的最後一件事是那種每個廠家的產品由上市日期,但讓他們在生產商層次進行分組 - 這裏的一切我想要做的事:

           Sales 
Manufacturer Product Name Product Launch Date  
Apple  iPod   2001-10-23    34 
      iPad   2010-04-03    30 
Samsung  Galaxy  2009-04-27    24 
      Galaxy Tab 2010-09-02    22 

當我嘗試sortlevel()我失去了漂亮的每個公司的領導層,我以前還:

> grouped.sortlevel('Product Launch Date') 
               Sales 
Manufacturer Product Name Product Launch Date  
Apple  iPod   2001-10-23    34 
Samsung  Galaxy  2009-04-27    24 
Apple  iPad   2010-04-03    30 
Samsung  Galaxy Tab 2010-09-02    22 

排序()和sort_index()只是失敗:

grouped.sort(['Manufacturer','Product Launch Date']) 
KeyError: u'no item named Manufacturer' 

grouped.sort_index(by=['Manufacturer','Product Launch Date']) 
KeyError: u'no item named Manufacturer' 

看起來像一個簡單的操作,但我不能弄明白。

我並沒有爲此使用MultiIndex,但由於這是groupby()返回的結果,這就是我一直在使用的。

BTW產生初始數據框的代碼是:

data = { 
    'Date': ['2013-01-01', '2013-01-01', '2013-01-01', '2013-01-01', '2013-01-02', '2013-01-02', '2013-01-02', '2013-01-02'], 
    'Manufacturer' : ['Apple', 'Apple', 'Samsung', 'Samsung', 'Apple', 'Apple', 'Samsung', 'Samsung',], 
    'Product Name' : ['iPod', 'iPad', 'Galaxy', 'Galaxy Tab', 'iPod', 'iPad', 'Galaxy', 'Galaxy Tab'], 
    'Product Launch Date' : ['2001-10-23', '2010-04-03', '2009-04-27', '2010-09-02','2001-10-23', '2010-04-03', '2009-04-27', '2010-09-02'], 
    'Sales' : [12, 13, 14, 15, 22, 17, 10, 7] 
} 
df = DataFrame(data, columns=['Date', 'Manufacturer', 'Product Name', 'Product Launch Date', 'Sales']) 
+1

「數據將按照選定的級別按字典順序排序*其次是其他級別(按順序)*」(這很糟糕......) –

回答

8

一個黑客會改變級別的順序:

In [11]: g 
Out[11]: 
               Sales 
Manufacturer Product Name Product Launch Date 
Apple  iPad   2010-04-03    30 
      iPod   2001-10-23    34 
Samsung  Galaxy  2009-04-27    24 
      Galaxy Tab 2010-09-02    22 

In [12]: g.index = g.index.swaplevel(1, 2) 

Sortlevel,它(如你發現)爲了排序多指標水平:

In [13]: g = g.sortlevel() 

和交換回:

In [14]: g.index = g.index.swaplevel(1, 2) 

In [15]: g 
Out[15]: 
               Sales 
Manufacturer Product Name Product Launch Date 
Apple  iPod   2001-10-23    34 
      iPad   2010-04-03    30 
Samsung  Galaxy  2009-04-27    24 
      Galaxy Tab 2010-09-02    22 

我認爲sortlevel不應該按順序對剩餘的標籤進行排序,所以會創建一個github問題。 :)雖然值得一提的是關於"the need for sortedness"的docnote。

注:

g = df.groupby(['Manufacturer', 'Product Launch Date', 'Product Name']).sum() 
+1

[This doc note](http: /pandas.pydata.org/pandas-docs/dev/indexing.html#the-need-for-sortedness)表明這些級別需要進行排序,但顯然這只是一個實現細節。目前尚不清楚這是否意味着它們必須按照從最高到最低索引級別進行分級排序。 – BrenBarn

+0

@BrenBarn這是一個很好的觀點,我聽說過傑夫之前對此有所瞭解:) :) –

+0

順便說一句,您不能通過以交換順序執行初始groupby來消除解決方案中的額外交換/排序(然後只是在團體之後swaplevel)? – BrenBarn

0

如果你想盡量避免了非常深刻的多指標內的多個互換,你也可以用這個搜索:您可以通過重新排序初始GROUPBY的順序避開第一swaplevel

  1. X級切片(按列表理解+。LOC + IndexSlice)
  2. 排序所期望的水平(sortlevel(2))
  3. 串連各組級X指標

這裏有代碼:

import pandas as pd 
idx = pd.IndexSlice 
g = pd.concat([grouped.loc[idx[i,:,:],:].sortlevel(2) for i in grouped.index.levels[0]]) 
g 
0

如果你不關心保存索引(我通常更喜歡一個任意的整數索引),你可以使用下面的一行:

grouped.reset_index().sort(["Manufacturer","Product Launch Date"]) 
3

這其中內襯爲我的作品:

In [1]: groupd.sortlevel(["Manufacturer","Product Launch Date"], sort_remaining=False) 

               Sales 
Manufacturer Product Name Product Launch Date  
Apple  iPod   2001-10-23    34 
      iPad   2010-04-03    30 
Samsung  Galaxy  2009-04-27    24 
      Galaxy Tab 2010-09-02    22 

注意這個工程太:

groups.sortlevel([0,2], sort_remaining=False) 

這個就不用當你最初發布兩年多前,曾因爲sortlevel默認排序在所有指數這會破壞你的公司層次結構。 sort_remaining它禁用了去年添加的行爲。這裏是供參考的提交鏈接:https://github.com/pydata/pandas/commit/3ad64b11e8e4bef47e3767f1d31cc26e39593277

+1

感謝您發佈更新的答案。我有一個三級多指標,只想在前兩名中排序。這工作完美。 –