Многоуровневый индекс / Продвинутая индексация
В этом разделе рассматривается индексация с помощью MultiIndex и более продвинутые возможности индексации.
См. Индексация и выбор данных для общей документации по индексации.
Предупреждение
Возвращается копия или ссылка при выполнении операции задания, может зависеть от контекста. Иногда это называется chained assignment и следует избегать. См. Возврат представления или копии
Предупреждение
В версии 0.15.0 Index был внутренне переработан, чтобы больше не наследовать от ndarray, а вместо этого наследовать от PandasObject, аналогично остальным объектам pandas. Это должно быть прозрачное изменение с очень ограниченными последствиями для API (см. Внутренняя рефакторизация)
См. справочник для некоторых продвинутых стратегий
Иерархическая индексация (MultiIndex)
Иерархическая/многоуровневая индексация очень интересна, поскольку открывает двери для достаточно сложного анализа и обработки данных, особенно при работе с данными высокой размерности. По сути, она позволяет хранить и обрабатывать данные с произвольным числом измерений в структурах данных меньшей размерности, таких как Series (1d) и DataFrame (2d).
В этом разделе мы покажем, что именно мы подразумеваем под «иерархической» индексацией и как она интегрируется со всеми функциями индексации pandas, описанными выше и в предыдущих разделах. Позже, когда мы будем обсуждать группировку и преобразование и изменение структуры данных, мы покажем нетривиальные примеры, чтобы проиллюстрировать, как она помогает в структурировании данных для анализа.
См. справочник для некоторых продвинутых стратегий
Создание объекта MultiIndex (иерархический индекс)
Объект MultiIndex является иерархическим аналогом стандартного объекта Index, который обычно хранит метки осей в объектах pandas. Можно представить себе MultiIndex как массив кортежей, где каждый кортеж является уникальным. MultiIndex можно создать из списка массивов (используя MultiIndex.from_arrays), массива кортежей (используя MultiIndex.from_tuples) или пересечения наборов итерируемых объектов (используя MultiIndex.from_product). Конструктор Index будет пытаться вернуть MultiIndex, когда ему передается список кортежей. Следующие примеры демонстрируют разные способы инициализации MultiIndexes.
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(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
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(levels=[['bar', 'baz', 'foo', 'qux'], ['one', 'two']],
labels=[[0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 0, 1, 0, 1, 0, 1]],
names=['first', 'second'])
Для удобства вы можете напрямую передать список массивов в Series или DataFrame для автоматического построения MultiIndex:
In [10]: arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),
....: np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
....:
In [11]: s = pd.Series(np.random.randn(8), index=arrays)
In [12]: s
Out[12]:
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 [13]: df = pd.DataFrame(np.random.randn(8, 4), index=arrays)
In [14]: df
Out[14]:
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 [15]: df.index.names Out[15]: FrozenList([None, None])
Этот индекс может быть основой любой оси объекта pandas, а количество уровней индекса зависит от вас:
In [16]: df = pd.DataFrame(np.random.randn(3, 8), index=['A', 'B', 'C'], columns=index) In [17]: df Out[17]: first bar baz foo qux \ second one two one two one two one A 0.895717 0.805244 -1.206412 2.565646 1.431256 1.340309 -1.170299 B 0.410835 0.813850 0.132003 -0.827317 -0.076467 -1.187678 1.130127 C -1.413681 1.607920 1.024180 0.569605 0.875906 -2.211372 0.974466 first second two A -0.226169 B -1.436737 C -2.006747 In [18]: 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.20.3/advanced.html