groupby на многоиндексном уровне и удаление уровня группировки

#python #pandas #pandas-groupby #multi-index

#python #панды #pandas-groupby #многоиндексный

Вопрос:

Я выполняю операцию groupby над фреймом данных pandas, который в качестве примера может выглядеть так:

 import pandas as pd
import numpy as np

numbers = [0, 1, 2]
colors = ['green', 'purple']
mx = pd.MultiIndex.from_product([colors, numbers], names=['color', 'numbers'])

values = np.random.rand(6)

df = pd.DataFrame(values, mx)
df = df.drop(index=("green", 2))
  

(пример индекса взят из pandas docs на multiindex)

Затем я хочу выполнить групповую операцию, например "color" , на уровне, но я не хочу, чтобы color оставался индексом в сгруппированном series , поскольку он становится избыточным.

 for key, series in df.groupby("color"):
    print(f"{key = }")
    print(f"Expected index: {series.index.droplevel('color').to_list()}")
    print(f"Actual index: {series.index.to_list()}")
    print()
  

который выводит:

 key = 'green'
Expected index: [0, 1]
Actual index: [('green', 0), ('green', 1)]

key = 'purple'
Expected index: [0, 1, 2]
Actual index: [('purple', 0), ('purple', 1), ('purple', 2)]
  

Поскольку сгруппированный уровень "color" одинаков для каждой группировки, он избыточен, и мне просто нужны значения уровня "numbers" .

Я мог бы просто сбросить уровень внутри цикла, как это сделано здесь, но мне было интересно, есть ли другие способы достижения этого, которые я пропустил?

Комментарии:

1. С какой именно операцией вы пытаетесь это сделать groupby ?

2. @QuangHoang В этом случае я перебираю группы, чтобы отобразить их, и мне нужен цвет (или животное) в качестве метки, числа как x и значения как y. Но я могу представить, что есть и другие варианты использования.

Ответ №1:

IIUC, вы можете просто проиндексировать свой фрагмент вашего фрейма данных с помощью ключа:

 for key, series in df.groupby("color"):
    print(f'Key: {key}')
    print(series.loc[key])
    print('n')
  

Вывод:

 Key: green
                0
numbers          
0        0.913962
1        0.457205


Key: purple
                0
numbers          
0        0.939128
1        0.778389
2        0.715971
  

Ответ №2:

Похоже, вы хотите перебрать значение первого уровня. Вы можете просто попробовать:

 for color in df.index.get_level_values('color').unique():
    series = df.loc[color]
    print(color)
    print(series)
  

Вывод:

 green
                0
numbers          
0        0.161444
1        0.403312
purple
                0
numbers          
0        0.369750
1        0.222223
2        0.565426
  

Комментарии:

1. Спасибо, в моем примере это сработало бы, но это не сработало бы, если бы я смотрел на группы, где метка может быть двухуровневой. Вы также можете использовать df.index.unique("color") , что было бы более читабельным.