Многоуровневый индекс / расширенный индексирование
В этом разделе рассматривается индексирование с многоуровневым индексом и другие расширенные функции индексирования.
См. Индексирование и выбор данных для общей документации по индексированию.
Предупреждение
Возвращаемый тип (копия или ссылка) при операции присваивания может зависеть от контекста. Это иногда называется chained assignment и следует избегать. См. Возвращение представления или копии.
См. справочник для некоторых расширенных стратегий.
Иерархическое индексирование (MultiIndex)
Иерархическое/многоуровневое индексирование очень полезно, поскольку оно открывает возможности для довольно сложного анализа и обработки данных, особенно при работе с данными высокой размерности. По сути, это позволяет хранить и обрабатывать данные с произвольным числом измерений в структурах данных меньшей размерности, таких как Series (1d) и DataFrame (2d).
В этом разделе мы покажем, что именно мы подразумеваем под «иерархическим» индексированием и как оно интегрируется со всеми функциями индексирования pandas, описанными выше и в предыдущих разделах. Позже, при обсуждении группировки и преобразования данных, мы покажем нетривиальные применения, чтобы проиллюстрировать, как это помогает в структурировании данных для анализа.
См. справочник для некоторых расширенных стратегий.
Изменено в версии 0.24.0: MultiIndex.labels было переименовано в MultiIndex.codes, а MultiIndex.set_labels в MultiIndex.set_codes.
Создание объекта MultiIndex (иерархический индекс)
Объект MultiIndex является иерархическим аналогом стандартного объекта Index, который обычно хранит метки осей в объектах pandas. Можно представить MultiIndex как массив кортежей, где каждый кортеж уникален. MultiIndex можно создать из списка массивов (используя MultiIndex.from_arrays()), массива кортежей (используя MultiIndex.from_tuples()), перекрещенного набора итерируемых объектов (используя MultiIndex.from_product()) или DataFrame (используя MultiIndex.from_frame()). Конструктор Index попытается вернуть MultiIndex при передаче списка кортежей. Следующие примеры демонстрируют различные способы инициализации MultiIndex.
In [1]: arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
...: ['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
...:
In [2]: tuples = list(zip(*arrays))
In [3]: tuples
Out[3]:
[('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')]
In [4]: index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
In [5]: index
Out[5]:
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])
In [6]: s = pd.Series(np.random.randn(8), index=index)
In [7]: s
Out[7]:
first second
bar one 0.469112
two -0.282863
baz one -1.509059
two -1.135632
foo one 1.212112
two -0.173215
qux one 0.119209
two -1.044236
dtype: float64
Когда вам нужны все пары элементов из двух итерируемых объектов, использование метода MultiIndex.from_product() может быть проще:
In [8]: iterables = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
In [9]: pd.MultiIndex.from_product(iterables, names=['first', 'second'])
Out[9]:
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])
Вы также можете создать MultiIndex из DataFrame напрямую, используя метод MultiIndex.from_frame(). Это дополнительный метод к MultiIndex.to_frame().
Введено в версии 0.24.0.
In [10]: df = pd.DataFrame([['bar', 'one'], ['bar', 'two'],
....: ['foo', 'one'], ['foo', 'two']],
....: columns=['first', 'second'])
....:
In [11]: pd.MultiIndex.from_frame(df)
Out[11]:
MultiIndex([('bar', 'one'),
('bar', 'two'),
('foo', 'one'),
('foo', 'two')],
names=['first', 'second'])
Для удобства вы можете передать список массивов напрямую в Series или DataFrame для автоматического создания MultiIndex:
In [12]: arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),
....: np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
....:
In [13]: s = pd.Series(np.random.randn(8), index=arrays)
In [14]: s
Out[14]:
bar one -0.861849
two -2.104569
baz one -0.494929
two 1.071804
foo one 0.721555
two -0.706771
qux one -1.039575
two 0.271860
dtype: float64
In [15]: df = pd.DataFrame(np.random.randn(8, 4), index=arrays)
In [16]: df
Out[16]:
0 1 2 3
bar one -0.424972 0.567020 0.276232 -1.087401
two -0.673690 0.113648 -1.478427 0.524988
baz one 0.404705 0.577046 -1.715002 -1.039268
two -0.370647 -1.157892 -1.344312 0.844885
foo one 1.075770 -0.109050 1.643563 -1.469388
two 0.357021 -0.674600 -1.776904 -0.968914
qux one -1.294524 0.413738 0.276662 -0.472035
two -0.013960 -0.362543 -0.006154 -0.923061
Все конструкторы MultiIndex принимают аргумент names, который хранит строковые имена самих уровней. Если имена не указаны, будет использоваться None:
In [17]: df.index.names Out[17]: FrozenList([None, None])
Этот индекс может поддерживать любую ось объекта pandas, а количество **уровней** индекса зависит от вас:
In [18]: df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index) In [19]: df Out[19]: first bar baz foo qux second one two one two one two one two A 0.895717 0.805244 -1.206412 2.565646 1.431256 1.340309 -1.170299 -0.226169 B 0.410835 0.813850 0.132003 -0.827317 -0.076467 -1.187678 1.130127 -1.436737 C -1.413681 1.607920 1.024180 0.569605 0.875906 -2.211372 0.974466 -2.006747 In [20]: pd.DataFrame(np.random.randn(6, 6), index=index[:6], columns=index[:6])
© 2008–2012, AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team
Licensed under the 3-clause BSD License.
https://pandas.pydata.org/pandas-docs/version/0.25.0/user_guide/advanced.html