Заполнение строк в DataFrame, полученном агрегированием

Получаемый агрегированием

df_2 = df_1.groupby(['US','Data','Summa']).agg({'Summa': 'count'})
df_2.rename(columns={'Summa': 'S'})

DatаFrame df2 имеет такой вид

DatаFrame

То есть в столбцах US и Data только заголовки подгрупп, и при выгрузке в Excel получаются объединённые ячейки, которые нельзя потом отфильтровать и и отсортировать. Можно средствами Python в полученном DatаFrame заполнить значения столбцов US и Data заголовками подгрупп в каждой строке ? Если честно, я не очень понимаю, что за объект из одного столбца получается в результате агрегирования, потому что

df_2.info()

показывает

<class 'pandas.core.frame.DataFrame'>
MultiIndex: 321373 entries, ('J308616', Timestamp('2020-06-09 00:00:00'), np.int64(100)) to ('J311795', Timestamp('2024-03-15 00:00:00'), np.int64(5000))
Data columns (total 1 columns):
 #   Column  Non-Null Count   Dtype
---  ------  --------------   -----
 0   Summa   321373 non-null  int64
dtypes: int64(1)

Ответы (1 шт):

Автор решения: Vitalizzare

Применение метода reset_index к полученной таблице будет достаточно.

Ошибка ValueError: cannot insert Summa, already exists возникает из-за того, что строка df_2.rename(columns={'Summa': 'S'}) возвращает копию таблицы df_2 с переименованным столбцом. Сама же таблица df_2 остаётся неизменной, поэтому применив к ней reset_index вы сталкиваетесь с конфликтом имен столбца 'Summa' с именем третьего уровня индекса таблицы.

Один из способов исправить ситуацию - сделать переименование столбца до присвоения результата переменной df_2. Там же сразу после переименования можно переместить индексы в столбцы:

df_2 = (
    df_1
    .groupby(['US','Data','Summa'])
    .agg({'Summa': 'count'})
    .rename(columns={'Summa': 'S'})
    .reset_index()
)

Второй способ - использовать во второй строке исходного кода либо присвоение df_2 = df_2.rename(...), либо добавить параметр inplace=True:

df_2.rename(columns={'Summa': 'S'}, inplace=True)

Что касается подхода к подсчету уникальных значений, то я бы облегчил группировку, убрав из неё 'Summa' и применив метод value_counts, который вернет Series по имени 'count'. К полученной последовательности также можно применить метод reset_index, и здесь имя 'count' не конфликтует с именами уровней индекса:

df_2 = df_1.groupby(['US', 'Data'])['Summa'].value_counts().reset_index()

В любом случае, последующее df_2.to_excel('book_name.xlsx', index=None) создаст таблицу Excel без сгруппированных ячеек, как в случае с многоуровневым индексом.

→ Ссылка