GroupBy на фрейме данных с многоиндексными столбцами с использованием periodindex - PullRequest
0 голосов
/ 12 июня 2019

У меня есть pivot_table сгенерированный DataFrame с одним индексом для его строк и MultiIndex для его столбцов.Верхний уровень MultiIndex - это имя данных, по которым я выполняю вычисления, а второй уровень - это ДАТА этих данных.Значения являются результатом этих расчетов.Это выглядит так:

Imgur link - моя репутация недостаточно высока для публикации встроенных изображений

Я пытаюсь сгруппировать эти данные по кварталам (например, Q42018)вместо каждого дня (собственный формат данных).

Я нашел эту запись, которая использует PeriodIndex и GroupBy для преобразования индекса дат в индекс кварталов / лет длябыть довольно элегантным и иметь больше смысла.

Проблема в том, что это решение для фрейма данных только с одним столбцом индекса.Я столкнулся с проблемой, пытаясь сделать это, потому что мои столбцы многоиндексные, и я не могу понять, как заставить его работать.Вот моя попытка:

bt = cleaned2018_df.pivot_table(index='Broker',
                                values=['Interaction Id','Net Points'],
                                columns='Date',
                                aggfunc={'Interaction Id':pd.Series.nunique,
                                         'Net Points':np.sum}, 
                                fill_value=0)

pidx = pd.PeriodIndex(bt.columns.levels[1], freq='Q')
broker_qtr_totals = bt.groupby(pidx, axis=1, level=1).sum()

Как видите, я беру второй уровень MultiIndex, содержащий все даты, и запускаю его через функцию PeriodIndex, чтобы получитьназад индекс кварталов.Затем я передаю это PeriodIndex в groupby и приказываю ему работать со столбцами и вторым уровнем, на котором находятся даты.

Возвращает ValueError ответ Grouper and axis must be same length.И я знаю, что причина в том, что значение pidx, которое я передаю GroupBy, имеет длину x, тогда как ось столбца информационного кадра имеет длину 2x (так как 1-й уровень мультииндекса имеет 2 значения).

Я просто зациклен на том, как правильно применить это ко всему индексу.Кажется, я не могу понять это синтаксически, поэтому я хотел положиться на опыт сообщества, чтобы посмотреть, может ли кто-нибудь помочь мне.

Если мое объяснение не ясно, я с удовольствием уточню дальше.Заранее спасибо.

1 Ответ

0 голосов
/ 12 июня 2019

Я понял это и собираюсь опубликовать ответ на случай, если кто-нибудь еще с подобной проблемой приземлится здесь. Я правильно думал о проблеме, но в моей первой попытке было несколько ошибок.

Ошибка длины произошла из-за того, что я передал явную ссылку на 2-й уровень MultiIndex в функцию PeriodIndex, а затем передал ее в groupby. Лучшее решение - использовать функцию .get_level_values, поскольку она учитывает многоуровневую природу индекса и возвращает соответствующее количество значений на основе количества элементов на более высоких уровнях.

Например, если у вас есть DataFrame со столбцами MultiIndex с 2 уровнями, и каждый из этих 2 уровней содержит 3 значения, ваша таблица будет иметь 9 столбцов, так как нижний уровень разбит на каждое значение верхнего уровня. Мое первоначальное решение было просто получить эти 3 значения со второго уровня напрямую, вместо всех 9. get_level_values исправляет это.

Вторая проблема заключалась в том, что я сам передавал только этот PeriodIndex объект в группу. Это будет работать, но тогда это просто игнорирует верхний уровень MultiIndex. Поэтому вам нужно обязательно передать список, который содержит исходный верхний уровень и ваш новый второй уровень, по которому вы хотите сгруппироваться.

Исправленный код:

#use get_level_values instead of accessing levels directly
pIdx = pd.PeriodIndex(bt.columns.get_level_values(1), freq='Q')

# to maintain original grouping, pass in a list of your original top level, 
# and the new second level
broker_qtr_totals = bt.groupby(by=[bt.columns.get_level_values(0), pidx],
                               axis=1).sum()

Это работает

imgur ссылка на изображение с данным кадром, так как мой представитель слишком низкий

...