熊猫中的多指数排序

时间:2013-06-21 19:32:04

标签: python sorting pandas multi-index

我有一个通过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()和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生成初始DataFrame的代码是:

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'])

5 个答案:

答案 0 :(得分: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,(如您所见)按顺序对MultiIndex级别进行排序:

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"的文档。< / p>

注意:您可以通过重新排序初始groupby的顺序来避免第一个swaplevel

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

答案 1 :(得分: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

答案 2 :(得分:0)

如果你想尽量避免在一个非常深的MultiIndex中进行多次交换,你也可以试试这个:

  1. 按级别X(按列表推导+ .loc + IndexSlice)切片
  2. 对所需级别(sortlevel(2))进行排序
  3. 连接每组X级索引
  4. 这里有代码:

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

答案 3 :(得分:0)

如果您不关心保存索引(我通常更喜欢任意整数索引),您可以使用以下单行:

RewriteEngine On

RewriteCond %{DOCUMENT_ROOT}/HiddenFiles/$1 -f
RewriteRule ^([^/]+)$ /HiddenFiles/$1 [L]

RewriteRule ^([^/]+)$ /resizer.php?img=$1 [L]

答案 4 :(得分:0)

要按“索引列”(也称为级别)对MultiIndex进行排序,您需要使用.sort_index()方法并设置其level参数。如果要按多个级别排序,则需要将参数设置为按顺序排列的级别名称列表。

这应该为您提供所需的数据框:

df.groupby(['Manufacturer', 'Product Name', 'Launch Date']).sum().sort_index(level=['Manufacturer','Launch Date'])