Индексирование с помощью MultiIndex / Продвинутое индексирование
В этом разделе рассматривается индексирование с помощью MultiIndex и более продвинутые возможности индексирования.
Для получения общей информации об индексировании см. Индексирование и выбор данных.
Предупреждение
Возвращение копии или ссылки при операции установки может зависеть от контекста. Это иногда называется chained assignment и следует избегать. См. Возвращение представления или копии.
См. справочник по рецептам для некоторых продвинутых стратегий
Иерархическое индексирование (MultiIndex)
Иерархическое/многоуровневое индексирование очень перспективно, поскольку открывает возможности для довольно сложного анализа и обработки данных, особенно при работе с данными высокой размерности. По сути, оно позволяет хранить и обрабатывать данные с произвольным числом измерений в структурах данных меньшей размерности, таких как Series (1d) и DataFrame (2d).
В этом разделе мы покажем, что именно мы подразумеваем под «иерархическим» индексированием и как оно интегрируется со всеми функциями индексирования pandas, описанными выше и в предыдущих разделах. Позже, при обсуждении группировки и преобразования формы данных, мы покажем нетривиальные применения, чтобы проиллюстрировать, как это помогает структурировать данные для анализа.
См. справочник по рецептам для некоторых продвинутых стратегий
Создание объекта MultiIndex (иерархический индекс)
Объект MultiIndex является иерархическим аналогом стандартного объекта Index, который обычно хранит метки осей в объектах pandas. Можно представить MultiIndex как массив кортежей, где каждый кортеж уникален. Объект MultiIndex может быть создан из списка массивов (используя MultiIndex.from_arrays), массива кортежей (используя MultiIndex.from_tuples) или пересечения набора итерируемых объектов (используя MultiIndex.from_product). Конструктор 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(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.21.1/advanced.html