0Pricing
Pandas & NumPy Academy · Урок

Выбор данных из MultiIndex

Получайте данные на внешнем и внутреннем уровнях индекса с помощью .loc, используя кортежи, срезы и вспомогательный объект pd.IndexSlice.

«Выбор данных из MultiIndex» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Навигация по иерархическим данным

После создания MultiIndex Вам понадобятся эффективные способы извлечения подмножеств данных. Pandas предоставляет для этого три инструмента: .loc с кортежами для точного выбора по метке, slice() и pd.IndexSlice для выбора диапазона по уровням и .xs() для выбора поперечного среза по значению определённого уровня. Освоив эти способы доступа, Вы раскроете все возможности иерархической индексации.

import pandas as pd
import numpy as np

# Setup: GDP data by country and year
df_flat = pd.DataFrame({
    'country': ['USA','USA','USA','UK','UK','UK','DE','DE','DE'],
    'year': [2021, 2022, 2023, 2021, 2022, 2023, 2021, 2022, 2023],
    'gdp_bn': [23000, 25000, 26000, 3000, 3100, 3200, 4100, 4200, 4350]
})
df = df_flat.set_index(['country', 'year']).sort_index()
print(df)

Выбор по внешнему уровню с помощью .loc

Передайте в .loc[] одну метку внешнего уровня, чтобы получить все строки этой группы. Для двухуровневого MultiIndex (страна, год) выражение df.loc['USA'] возвращает все строки USA в виде DataFrame, в котором остаётся только внутренний индекс (год). Такое поведение называется удалением уровня: при выборе конкретного значения внешнего уровня Pandas удаляет этот уровень из индекса возвращаемого объекта.

import pandas as pd

df_flat = pd.DataFrame({
    'country': ['USA','USA','USA','UK','UK','UK'],
    'year': [2021, 2022, 2023, 2021, 2022, 2023],
    'gdp_bn': [23000, 25000, 26000, 3000, 3100, 3200]
})
df = df_flat.set_index(['country', 'year']).sort_index()

# Select all USA rows
usa = df.loc['USA']
print('All USA rows:')
print(usa)
print('\nRemaining index type:', usa.index.name)

Выбор конкретного кортежа с помощью .loc

Чтобы получить одну строку, определяемую обоими уровнями индекса, передайте кортеж в .loc[]: df.loc[('USA', 2022)]. Это возвращает Series (или скаляр для одного столбца), соответствующий ровно этой комбинации меток (внешняя, внутренняя). Если Вы хотите получить DataFrame, а не Series, кортеж необходимо передать внутри списка: df.loc[[('USA', 2022)]].

import pandas as pd

df_flat = pd.DataFrame({
    'country': ['USA','USA','USA','UK','UK','UK'],
    'year': [2021, 2022, 2023, 2021, 2022, 2023],
    'gdp_bn': [23000, 25000, 26000, 3000, 3100, 3200],
    'cpi': [3.2, 5.1, 4.8, 2.5, 3.4, 3.0]
})
df = df_flat.set_index(['country', 'year']).sort_index()

# Single row as Series
print('USA 2022 (Series):')
print(df.loc[('USA', 2022)])

# Single row as DataFrame
print('\nUSA 2022 (DataFrame):')
print(df.loc[[('USA', 2022)]])

Выбор нескольких строк с помощью списка кортежей

Чтобы одновременно выбрать несколько конкретных строк, передайте в .loc[] список кортежей. Это удобно, когда нужен разрозненный набор строк, определяемых составными ключами, — например, данные за 2022 год для USA и UK, но не для Германии. В результате MultiIndex сохраняется в возвращённом DataFrame.

import pandas as pd

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]
})
df = df_flat.set_index(['country', 'year']).sort_index()

# Select specific (country, year) combinations
subset = df.loc[[('USA', 2022), ('UK', 2023), ('DE', 2022)]]
print(subset)

Срезы с помощью pd.IndexSlice

pd.IndexSlice (обычно обозначаемый псевдонимом idx) позволяет задавать срезы диапазонов для уровней MultiIndex без ручного создания громоздких кортежей срезов. Синтаксис: df.loc[idx[outer_slice, inner_slice], column_slice]. Например, df.loc[idx['UK':'USA', 2022:2023], :] выбирает все строки, в которых внешний уровень находится между UK и USA, а внутренний — между 2022 и 2023 годами. Для корректной работы индекс должен быть отсортирован.

import pandas as pd
import numpy as np

years = [2021, 2022, 2023]
countries = ['DE', 'UK', 'USA']
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'gdp': np.random.randint(3000, 26000, 9)}, index=mi)

idx = pd.IndexSlice

# Select UK and USA for years 2022 and 2023
subset = df.loc[idx['UK':'USA', 2022:2023], :]
print(subset)

Доступ к поперечному срезу с помощью .xs()

df.xs(key, level=) выбирает все строки, в которых определённый уровень равен заданному значению, независимо от содержимого остальных уровней. В отличие от .loc, которому сначала нужно указать внешние уровни, .xs позволяет напрямую обратиться к любому уровню по имени. Например, df.xs(2022, level='year') возвращает все строки за 2022 год для всех стран без необходимости указывать 'USA', 'UK' или 'DE'.

import pandas as pd
import numpy as np

countries = ['DE', 'UK', 'USA']
years = [2021, 2022, 2023]
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'gdp': [4100,4200,4350, 3000,3100,3200, 23000,25000,26000]}, index=mi)

# All countries for year 2022 (inner level)
print('All data for year 2022:')
print(df.xs(2022, level='year'))

# All years for UK (outer level)
print('\nAll years for UK:')
print(df.xs('UK', level='country'))

Доступ к столбцам MultiIndex

Если DataFrame имеет MultiIndex у столбцов, используйте кортежи для доступа к конкретным столбцам: df[('revenue', 'Q1')]. Чтобы выбрать все столбцы внешнего уровня (например, все столбцы выручки), используйте df['revenue'] — это вернёт DataFrame со всеми столбцами внутреннего уровня, относящимися к этому внешнему ключу. Шаблон с pd.IndexSlice также работает с многоуровневыми индексами столбцов в сочетании с .loc.

import pandas as pd
import numpy as np

metrics = ['revenue', 'cost']
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
cols = pd.MultiIndex.from_product([metrics, quarters], names=['metric', 'quarter'])
df = pd.DataFrame(
    np.random.randint(50, 200, (3, 8)),
    columns=cols,
    index=['USA', 'UK', 'DE']
)

# Access all revenue columns
print('Revenue columns:')
print(df['revenue'])

# Access a specific cell
print('\nUSA revenue Q1:', df.loc['USA', ('revenue', 'Q1')])

Выбор внутреннего уровня для всех внешних ключей

Чтобы выбрать одно значение внутреннего уровня для всех значений внешнего уровня, объедините .loc со значением slice(None) для внешнего уровня: df.loc[(slice(None), 2022), :]. Это выбирает строку за 2022 год для каждой страны. Вариант с pd.IndexSlice читается понятнее: df.loc[idx[:, 2022], :]. Такой шаблон часто нужен, когда требуется получить снимок всех объектов на определённый момент времени.

import pandas as pd
import numpy as np

countries = ['DE', 'UK', 'USA']
years = [2021, 2022, 2023]
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({'gdp': [4100,4200,4350, 3000,3100,3200, 23000,25000,26000]}, index=mi)

idx = pd.IndexSlice

# All countries for year 2022 (using IndexSlice)
all_2022 = df.loc[idx[:, 2022], :]
print('All countries in 2022:')
print(all_2022)

Распространённые ошибки при выборе данных из MultiIndex

Три распространённые ошибки: 1) Несортированный индекс: срез несортированного MultiIndex вызывает UnsortedIndexError или возвращает неверные результаты — всегда сначала вызывайте sort_index(). 2) KeyError при использовании кортежа в качестве ключа: если передать кортеж без обёртки в .loc[], Python интерпретирует его как позиционную индексацию — для доступа к MultiIndex по меткам всегда используйте .loc. 3) Несоответствие уровней: после groupby имена уровней MultiIndex могут отличаться от ожидаемых — проверьте df.index.names перед созданием среза.

import pandas as pd

# Unsorted MultiIndex slicing
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)
# Sort before slicing
df = df.sort_index()
print('After sort:', df.index.is_monotonic_increasing)

idx = pd.IndexSlice
print('\nSlice A:')
print(df.loc[idx['A', :], :])

Практический пример: квартальная отчётность

Рассмотрим практический случай: у Вас есть данные о продажах с индексом (регион, квартал), и для отчёта за год нужно извлечь Q4 по всем регионам. Используйте .xs('Q4', level='quarter'), чтобы получить этот поперечный срез одним вызовом. Затем вычислите итог с помощью .sum(). Такой шаблон — агрегация через groupby → результат с MultiIndex → извлечение поперечного среза — чрезвычайно распространён в конвейерах подготовки бизнес-отчётности.

import pandas as pd
import numpy as np

regions = ['North', 'South', 'East', 'West']
quarters = ['Q1', 'Q2', 'Q3', 'Q4']
mi = pd.MultiIndex.from_product([regions, quarters], names=['region', 'quarter'])

np.random.seed(42)
df = pd.DataFrame({
    'sales': np.random.randint(200, 500, 16),
    'units': np.random.randint(50, 150, 16)
}, index=mi)

# Extract Q4 performance across all regions
q4 = df.xs('Q4', level='quarter')
print('Q4 Results by Region:')
print(q4)
print('\nQ4 Total Sales:', q4['sales'].sum())

Объединение выбора из MultiIndex со столбцами

Вы можете одновременно выбрать конкретные строки и столбцы с помощью .loc[row_indexer, column_list]. При работе с MultiIndex индексатором строк может быть кортеж, список кортежей или IndexSlice, а индексатором столбцов — имя столбца или список имён. Это позволяет одним выражением извлечь точную прямоугольную подтаблицу из иерархического DataFrame.

import pandas as pd
import numpy as np

countries = ['DE', 'UK', 'USA']
years = [2021, 2022, 2023]
mi = pd.MultiIndex.from_product([countries, years], names=['country', 'year'])
df = pd.DataFrame({
    'gdp': [4100,4200,4350, 3000,3100,3200, 23000,25000,26000],
    'inflation': [1.5, 2.1, 2.8, 2.0, 3.4, 2.9, 3.2, 5.1, 4.8],
    'unemployment': [5.0, 4.8, 4.5, 4.5, 4.2, 4.0, 3.8, 3.5, 3.3]
}, index=mi)

idx = pd.IndexSlice

# UK and USA, years 2022-2023, only gdp and inflation
result = df.loc[idx['UK':'USA', 2022:2023], ['gdp', 'inflation']]
print(result)

Быстрая проверка

Проверьте, насколько хорошо Вы поняли выбор данных из MultiIndex в этом уроке.

Итоги урока

В этом уроке Вы узнали, как использовать .loc с кортежами для выбора конкретных сочетаний меток (внешняя, внутренняя), pd.IndexSlice — для создания срезов диапазонов на любых уровнях, а .xs() — для извлечения поперечного среза на любом уровне независимо от внешних ключей. Всегда сначала сортируйте индекс, чтобы избежать UnsortedIndexError. Далее мы рассмотрим выравнивание индексов и переиндексацию — то, как Pandas выравнивает два DataFrames по общему индексу.

Часто задаваемые вопросы

Урок «Выбор данных из MultiIndex» бесплатный?

Да — полный текст урока «Выбор данных из MultiIndex» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Чему я научусь в уроке «Выбор данных из MultiIndex»?

Получайте данные на внешнем и внутреннем уровнях индекса с помощью .loc, используя кортежи, срезы и вспомогательный объект pd.IndexSlice. Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?

Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Выбор данных из MultiIndex»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?

Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Создание MultiIndex
  2. Выбор данных из MultiIndex
  3. Выравнивание и переиндексация
  4. Преимущества отсортированных индексов
← Назад к Pandas & NumPy Academy