Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Васильев Ю. - Python для data science (Библиотека программиста) - 2023.pdf
Скачиваний:
7
Добавлен:
07.04.2024
Размер:
7.21 Mб
Скачать

142      Глава 6. Агрегирование данных

West

243.0

2022-02-05 East

160.0

West

35.0

 

 

Поскольку в данном конкретном примере извлекаются данные о продажах за указанный период времени по всем регионам, можно не указывать названия регионов и передавать только даты:

df_date_region['2022-02-04':'2022-02-05']

Этот код должен вывести точно такой же результат, как и в предыдущем примере.

Срезы на разных уровнях агрегирования

Возможно, вам понадобятся срезы агрегированных значений на различных уровнях согласно иерархическому индексу. В нашем примере самым высоким уровнем агрегации является Date(дата), внутри него находится уровень Region (регион). Допустим, нам нужно получить данные о продажах для определенного среза дат, выбрав все содержимое уровня Region. Это можно сделать с помощью функции Python slice() в сочетании со свойством датафрейма loc, как показано ниже:

df_date_region.loc[(slice('2022-02-05', '2022-02-06'), slice(None)), :]

Здесь мы дважды использовали функцию slice(). В первом случае slice() определяет диапазон среза по дате (Date), самому высокому уровню агрегации.

Врезультате создается объект slice, указывающий начальную и конечную даты. Во второй раз slice()вызывается на уровне региона (Region). Это следующий, более низкий уровень. Указав None, мы выбираем все содержимое уровня Region.

Воператор [] свойства loc также включается запятая, за которой следует двоеточие (:). Этот синтаксис указывает, что используются метки строк, а не столбцов.

Врезультате получим следующий набор строк:

 

 

Total

Date

Region

 

2022-02-05

East

160.0

 

West

35.0

2022-02-06

East

110.0

 

West

86.0

 

 

 

Группировка и агрегирование данных      143

В следующем примере заменим slice(None) на slice('East'), тем самым сократив количество получаемых данных о продажах за указанный диапазон дат до строк, содержащих East:

df_date_region.loc[(slice('2022-02-05', '2022-02-06'), slice('East')), :]

Получим следующие строки:

 

 

Total

Date

Region

 

2022-02-05

East

160.0

2022-02-06

East

110.0

 

 

 

На уровне Region тоже можно указать не одно значение, а диапазон. Однако в данном конкретном примере этот диапазон может начинаться только с 'East' и заканчиваться 'West', что реализуется как: slice('East','West'). Поскольку это единственный возможный диапазон, вызов slice('East','West') будет эквивалентен вызову slice(None).

Добавление общего итога

Когда речь идет об агрегировании данных о продажах, в конечном счете может понадобиться рассчитать общий итог, или сумму всех итоговых значений продаж, и добавить его в датафрейм. Поскольку в нашем примере все итоговые значения находятся в одном датафрейме (df_date_region), можно использовать метод pandas sum() для нахождения общего объема продаж по всем регионам и всем датам. Данный метод вычисляет сумму значений по указанной оси, как показано ниже:

ps = df_date_region.sum(axis = 0) print(ps)

Здесь sum()возвращает объект pandas Series с суммарными значениями по столбцу Total датафрейма df_date_region. Помните, что указывать столбец Total при вызове sum() нет необходимости, поскольку эта функция автоматически применяется к любым числовым данным. Содержимое серии ps будет следующим:

Total 731.0 dtype: float64

144      Глава 6. Агрегирование данных

Чтобы добавить вновь созданную серию к датафрейму df_date_region, необходимо сначала дать ей имя. В датафрейме оно будет использоваться в качестве индекса строки с общим итогом. Поскольку ключи индексов в df_date_region являются кортежами, в качестве имени серии тоже нужно использовать кортеж:

ps.name=('All','All')

Первый 'All' в кортеже относится к составляющей индекса Date, а второй — к компоненту Region. Теперь серию можно добавить в датафрейм:

df_date_region_total = df_date_region.append(ps)

Вывод на экран только что созданного датафрейма будет выглядеть так:

 

 

Total

Date

Region

 

2022-02-04 East

97.0

 

West

243.0

2022-02-05

East

160.0

 

West

35.0

2022-02-06

East

110.0

 

West

86.0

All

All

731.0

 

 

 

Получить доступ к строке общего итога, как и к любой другой строке датафрейма, можно по ее индексу. Передадим кортеж, представляющий индекс строки, методу index.isin(), как делали ранее:

df_date_region_total[df_date_region_total.index.isin([('All', 'All')])]

В результате получим строку с общим итогом:

 

 

Total

Date

Region

 

All

All

731.0

 

 

 

Добавление промежуточных итогов

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

Группировка и агрегирование данных      145

Date

Region

Total

 

2022-02-04 East

97.0

 

West

243.0

All

All

340.0

2022-02-05 East

160.0

 

West

35.0

All

All

195.0

2022-02-06 East

110.0

 

West

86.0

All

All

196.0

All

All

731.0

 

 

 

Создание такого датафрейма потребует нескольких шагов. Сначала мы группируем датафрейм по уровню Date. Затем проходим по полученному объекту GroupBy, обращаясь к каждой дате с соответствующим набором строк (известным как субфрейм (subframe)), содержащих информацию о регионе и сумме для этой даты. Выбираем и добавляем каждый субфрейм в пустой датафрейм вместе с соответствующей строкой промежуточного итога. Таким образом:

df_totals = pd.DataFrame()

for date, date_df in df_date_region.groupby(level=0):df_totals = df_totals.append(date_df)

ps = date_df.sum(axis = 0)ps.name=(date,'All')

df_totals = df_totals.append(ps)

Начинаем с создания пустого датафрейма df_totals, в который будем помещать итоговые данные . Затем создаем объект GroupBy , группирующий df_date_region по верхнему иерархическому уровню индекса (level=0), то есть по столбцу Date, и проходим в цикле for по объекту GroupBy. На каждой итерации получаем дату и соответствующий ей субфрейм. Добавляем субфрейм к датафрейму df_totals , а затем создаем строку с промежуточным итогом в виде серии, содержащей сумму строк субфрейма . Затем присваиваем серии имя с соответствующей датой и 'All', чтобы обозначить все регионы , после чего серия добавляется к датафрейму df_totals .

Наконец, добавляем строку с итоговой суммой в датафрейм, как показано ниже:

df_totals = df_totals.append(df_date_region_total.loc[('All','All')])

В результате получаем датафрейм, который содержит как сумму продаж за каждую дату, так и общий итог за все даты.