Создание MultiIndex
Создавайте иерархический индекс строк с помощью pd.MultiIndex.from_tuples или set_index для нескольких столбцов и изучайте его уровни.
«Создание MultiIndex» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Что такое MultiIndex
MultiIndex (также называемый иерархическим индексом) позволяет DataFrame или Series Pandas иметь несколько уровней меток строк. Представьте его как составной ключ в базе данных: вместо идентификации строки по одной метке Вы идентифицируете её кортежем, например (страна, город) или (год, квартал). MultiIndexes необходимы для представления панельных данных, временных рядов с поперечными срезами и любых наборов данных с естественной двухуровневой структурой группировки.
import pandas as pd
# A simple example: sales by country and city
data = {
'sales': [100, 200, 150, 300, 80, 120]
}
index = pd.MultiIndex.from_tuples(
[('USA', 'New York'), ('USA', 'Chicago'),
('UK', 'London'), ('UK', 'Manchester'),
('DE', 'Berlin'), ('DE', 'Munich')],
names=['country', 'city']
)
df = pd.DataFrame(data, index=index)
print(df)Создание MultiIndex с помощью from_tuples
pd.MultiIndex.from_tuples(list_of_tuples, names=) — наиболее явный способ создать MultiIndex. Каждый кортеж становится одной меткой строки, а его элементы — уровнями. Параметр names задаёт имя каждому уровню, например ['year', 'quarter']. Этот метод удобен, когда у Вас уже есть подготовленный список составных ключей, который Вы хотите использовать в качестве индекса строк.
import pandas as pd
# Multi-level time index: year x quarter
tuples = [
(2022, 'Q1'), (2022, 'Q2'), (2022, 'Q3'), (2022, 'Q4'),
(2023, 'Q1'), (2023, 'Q2'), (2023, 'Q3'), (2023, 'Q4')
]
mi = pd.MultiIndex.from_tuples(tuples, names=['year', 'quarter'])
revenue = [120, 135, 145, 160, 130, 148, 162, 175]
df = pd.Series(revenue, index=mi, name='revenue_M')
print(df)Создание MultiIndex с помощью from_product
pd.MultiIndex.from_product(iterables, names=) создаёт MultiIndex на основе декартова произведения нескольких списков — всех возможных сочетаний элементов входных списков. Это самый удобный метод, когда в данных должны присутствовать все сочетания уровней. Например, все сочетания 3 лет × 4 кварталов × 5 регионов автоматически создают сбалансированную панель из 60 строк.
import pandas as pd
import numpy as np
years = [2021, 2022, 2023]
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
# Cartesian product: 3 years x 4 quarters = 12 combinations
mi = pd.MultiIndex.from_product([years, quarters], names=['year', 'quarter'])
print('Number of index entries:', len(mi))
print('First 6 entries:', mi[:6].tolist())
# Create a DataFrame with this index
df = pd.DataFrame({'revenue': np.random.randint(100, 200, 12)}, index=mi)
print('\n', df.head())Создание MultiIndex с помощью set_index
На практике чаще всего MultiIndex создают так: начинают с обычного DataFrame, содержащего столбцы для группировки, а затем вызывают df.set_index([col1, col2]). Эти столбцы преобразуются из столбцов данных в уровни индекса. Результат такой же, как при создании индекса с нуля с помощью from_tuples, но при работе с табличными данными требуется всего одна строка.
import pandas as pd
# Start with a flat DataFrame
df_flat = pd.DataFrame({
'country': ['USA', 'USA', 'UK', 'UK', 'DE', 'DE'],
'year': [2022, 2023, 2022, 2023, 2022, 2023],
'gdp_bn': [25000, 26000, 3100, 3200, 4200, 4350]
})
# Promote two columns to a MultiIndex
df = df_flat.set_index(['country', 'year'])
print(df)
print('\nIndex type:', type(df.index).__name__)
print('Index names:', df.index.names)Изучение уровней MultiIndex
MultiIndex хранит данные в уровнях (уникальных значениях каждого уровня) и кодах (целочисленных указателях на массивы уровней). Изучайте уровни с помощью df.index.levels или df.index.get_level_values(level). Используйте df.index.nlevels, чтобы проверить количество уровней. Атрибут names содержит имена, назначенные каждому уровню; задавайте их с помощью df.index.set_names(['level0', 'level1']).
import pandas as pd
df_flat = pd.DataFrame({
'country': ['USA', 'USA', 'UK', 'UK'],
'year': [2022, 2023, 2022, 2023],
'gdp': [25000, 26000, 3100, 3200]
})
df = df_flat.set_index(['country', 'year'])
print('Number of levels:', df.index.nlevels)
print('Level names:', df.index.names)
print('Level 0 values:', df.index.get_level_values(0).tolist())
print('Level 1 values:', df.index.get_level_values(1).tolist())
print('Unique level 0:', df.index.get_level_values('country').unique().tolist())MultiIndex для столбцов
MultiIndex можно также применить к столбцам, создав иерархию меток столбцов. Это распространённый подход при хранении нескольких показателей для каждой категории в структуре в стиле сводной таблицы — например, (выручка, Q1), (выручка, Q2), (затраты, Q1), (затраты, Q2). Обращайтесь к столбцам с MultiIndex так же, как к строкам, — используя кортежи. Создайте MultiIndex столбцов с помощью pd.MultiIndex.from_product и присвойте его df.columns.
import pandas as pd
import numpy as np
# Create a DataFrame with MultiIndex columns
metrics = ['revenue', 'cost']
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
col_index = pd.MultiIndex.from_product([metrics, quarters], names=['metric', 'quarter'])
data = np.random.randint(50, 200, size=(3, 8))
df = pd.DataFrame(data, columns=col_index, index=['USA', 'UK', 'DE'])
df.index.name = 'country'
print(df)MultiIndex после агрегации GroupBy
Когда Вы вызываете groupby([col1, col2]).agg(...), результирующий DataFrame получает MultiIndex строк (два ключа groupby становятся двумя уровнями индекса) и, возможно, MultiIndex столбцов (если Вы агрегируете несколько показателей). Чаще всего с MultiIndex сталкиваются именно так — при повседневном анализе данных. Понимание способов навигации по нему необходимо для работы с результатами groupby.
import pandas as pd
import seaborn as sns
tips = sns.load_dataset('tips')
# Two-key groupby creates a MultiIndex on rows
result = tips.groupby(['day', 'time'])['total_bill'].agg(['mean', 'count'])
print(result)
print('\nIndex type:', type(result.index).__name__)
print('Index names:', result.index.names)Перестановка и изменение порядка уровней
Используйте df.swaplevel(), чтобы поменять местами два уровня индекса, и df.reorder_levels([...]), чтобы изменить порядок всех уровней. Изменение порядка полезно, когда Вы хотите сначала выполнять срез по внутреннему уровню или когда у двух DataFrame уровни индекса расположены в разном порядке и их нужно выровнять перед объединением. После изменения порядка всегда вызывайте sort_index(), чтобы восстановить лексикографический порядок для эффективного формирования срезов.
import pandas as pd
import seaborn as sns
tips = sns.load_dataset('tips')
result = tips.groupby(['day', 'time'])['total_bill'].mean()
print('Original levels:', result.index.names)
# Swap so time is the outer level
swapped = result.swaplevel().sort_index()
print('\nSwapped levels:', swapped.index.names)
print(swapped.head())Проверка и сортировка MultiIndex
Формирование срезов MultiIndex эффективно только тогда, когда индекс отсортирован лексикографически. Проверьте, отсортирован ли индекс, с помощью df.index.is_monotonic_increasing. Если возвращается False, выполните сортировку с помощью df.sort_index(). Несортированный MultiIndex вызывает PerformanceWarning при операциях со срезами и в некоторых крайних случаях может возвращать неверные результаты — всегда сортируйте MultiIndex после создания или изменения.
import pandas as pd
# Create an unsorted MultiIndex deliberately
tuples = [('B', 2), ('A', 1), ('B', 1), ('A', 2)]
mi = pd.MultiIndex.from_tuples(tuples, names=['letter', 'num'])
df = pd.DataFrame({'value': [10, 20, 30, 40]}, index=mi)
print('Is sorted:', df.index.is_monotonic_increasing)
print('Before sorting:')
print(df)
df_sorted = df.sort_index()
print('\nAfter sorting:')
print(df_sorted)
print('Is sorted:', df_sorted.index.is_monotonic_increasing)Преобразование MultiIndex обратно в столбцы
Вызовите df.reset_index(), чтобы преобразовать все уровни индекса обратно в обычные столбцы, оставив DataFrame с простым целочисленным RangeIndex. Это распространённый приём после агрегации groupby: сначала вычислите сгруппированную сводку с MultiIndex, затем сбросьте индекс, чтобы получить плоский DataFrame, подходящий для дальнейших операций Pandas, объединения или экспорта в CSV. Используйте reset_index(level='name'), чтобы сбросить только один уровень двухуровневого индекса.
import pandas as pd
import seaborn as sns
tips = sns.load_dataset('tips')
result = tips.groupby(['day', 'time'])['total_bill'].mean()
print('MultiIndex result:')
print(result.head(4))
# Flatten back to a regular DataFrame
flat = result.reset_index()
print('\nFlattened DataFrame:')
print(flat.head(4))
print('Index type:', type(flat.index).__name__)Когда следует использовать MultiIndex
Используйте MultiIndex, когда Ваши данные имеют естественную иерархическую структуру: временные ряды с детализацией меньше дня (дата + час), панельные данные (объект + период времени) или вложенные группировки (страна + регион + город). Не используйте MultiIndexes для простых ключей группировки из двух столбцов, если плоский DataFrame с отдельными столбцами столь же понятен. Если Вам постоянно приходится вызывать reset_index() только для доступа к данным, это признак того, что MultiIndex не приносит пользы в Вашем рабочем процессе.
Быстрая проверка
Проверьте, насколько Вы поняли создание MultiIndex из этого урока.
Итоги урока
В этом уроке Вы узнали, что MultiIndexes предоставляют иерархические метки строк (или столбцов) с использованием кортежей, создаются с помощью from_tuples, from_product или set_index для нескольких столбцов и всегда должны быть отсортированы для эффективного формирования срезов. Далее мы рассмотрим выбор данных из MultiIndex с помощью .loc, кортежей, срезов и вспомогательного средства IndexSlice.
Часто задаваемые вопросы
Урок «Создание MultiIndex» бесплатный?
Да — полный текст урока «Создание MultiIndex» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Создание MultiIndex»?
Создавайте иерархический индекс строк с помощью pd.MultiIndex.from_tuples или set_index для нескольких столбцов и изучайте его уровни. Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Создание MultiIndex»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Создание MultiIndex
- Выбор данных из MultiIndex
- Выравнивание и переиндексация
- Преимущества отсортированных индексов