Многоиндексная сортировка в пандах

У меня есть мультииндексный DataFrame, созданный с помощью операции groupby. Я пытаюсь сделать сложный вид, используя несколько уровней индекса, но я не могу найти функцию сортировки, которая делает то, что мне нужно.

Первоначальный набор данных выглядит примерно так (ежедневный объем продаж различных продуктов):

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 (), с этим я работаю.

Кстати, код для создания исходного 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']) 

4 Solutions collect form web for “Многоиндексная сортировка в пандах”

Взлом заключался бы в изменении порядка уровней:

 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. 🙂 Хотя стоит упомянуть документ о «необходимости сортировки» .

Примечание: вы могли бы избежать первого swaplevel порядок начальной группы:

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

Этот один лайнер работает для меня:

 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 по умолчанию сортировался по индексам ALL, которые сбросили иерархию вашей компании. sort_remaining, который отключает это поведение в прошлом году. Вот ссылка для ссылки: https://github.com/pydata/pandas/commit/3ad64b11e8e4bef47e3767f1d31cc26e39593277

Если вы хотите избежать множественных свопов в очень глубоком MultiIndex, вы также можете попробовать:

  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 

Если вы не обеспокоены сохранением индекса (я часто предпочитаю произвольный целочисленный индекс), вы можете просто использовать следующий однострочный:

 grouped.reset_index().sort(["Manufacturer","Product Launch Date"]) 
  • Как показать строку и график на одном и том же участке
  • ошибка numpy и pandas timedelta
  • Преобразование объекта DataFrameGroupBy в базу данных DataFrame
  • Создание пустой MultiIndex
  • python pandas: обратный порядок столбцов df
  • Изменение определенных значений в нескольких столбцах панда DataFrame сразу
  • Как рассчитать средние значения, сгруппированные по другому столбцу в Pandas
  • Создайте несколько столбцов в Pandas Dataframe из одной функции
  • Python - лучший язык программирования в мире.