MultiIndex в Pandas

MultiIndex — это индекс из нескольких уровней. Например, ключ строки «номер устройства + время измерения» можно хранить как иерархию из двух уровней, а не склеивать в одну строку. Многие операции (groupby, pivot, stack) сами возвращают MultiIndex.

Когда использовать

  • Несколько ключей одновременно: устройство + датчик + время.

  • Результат группировки по двум и более полям.

  • Отчёты «по периодам и категориям» в одной таблице.

Пример 1. Создание из кортежей

import pandas as pd

idx = pd.MultiIndex.from_tuples(
    [("bot1", "temp"), ("bot1", "hum"), ("bot2", "temp")],
    names=["device", "sensor"],
)
s = pd.Series([22.1, 55, 24.5], index=idx)
print(s)

Output:

device  sensor
bot1    temp      22.1
        hum       55.0
bot2    temp      24.5
dtype: float64

Пример 2. from_product

import pandas as pd

idx = pd.MultiIndex.from_product(
    [["bot1", "bot2"], ["temp", "hum"]],
    names=["device", "sensor"],
)
df = pd.DataFrame({"value": [22, 55, 24, 50]}, index=idx)
print(df)

Output:

               value
device sensor
bot1   temp       22
       hum        55
bot2   temp       24
       hum        50

Пример 3. Слайс по уровню

import pandas as pd

idx = pd.MultiIndex.from_product(
    [["bot1", "bot2"], ["temp", "hum"]], names=["d", "s"])
df = pd.DataFrame({"v": [22, 55, 24, 50]}, index=idx)
print(df.loc["bot1"])

Output:

     v
s
temp 22
hum  55

Пример 4. xs (cross-section)

import pandas as pd

idx = pd.MultiIndex.from_product(
    [["bot1", "bot2"], ["temp", "hum"]], names=["d", "s"])
df = pd.DataFrame({"v": [22, 55, 24, 50]}, index=idx)
print(df.xs("temp", level="s"))

Output:

      v
d
bot1  22
bot2  24

Пример 5. swaplevel и sort_index

import pandas as pd

idx = pd.MultiIndex.from_tuples(
    [("a", 2), ("a", 1), ("b", 1)], names=["x", "y"])
df = pd.DataFrame({"v": [10, 20, 30]}, index=idx)
df2 = df.swaplevel().sort_index()
print(df2)

Output:

      v
y x
1 a  20
  b  30
2 a  10

Пример 6. stack / unstack

import pandas as pd

df = pd.DataFrame({"temp": [22, 24], "hum": [55, 50]},
                  index=["bot1", "bot2"])
s = df.stack()
print(s)
print("---")
print(s.unstack())

Output:

bot1  temp    22
      hum     55
bot2  temp    24
      hum     50
dtype: int64
---
      temp  hum
bot1    22   55
bot2    24   50

Подводные камни

  • Для слайсов по нескольким уровням используют pd.IndexSlice: df.loc[pd.IndexSlice["bot1", :], :].

  • Несортированный MultiIndex тормозит и иногда выбрасывает PerformanceWarning — всегда делайте sort_index().

  • После reset_index() все уровни превращаются в столбцы.

См. также

Примечание

Лицензия и источники

Техническое описание адаптировано из официальной документации Pandas (https://pandas.pydata.org/docs/), BSD-3-Clause License. Перевод на русский, примеры и пояснения — © AlashEd Wiki.