分层/多级索引是非常令人兴奋的,因为它为一些相当复杂的数据分析和操作打开了大门,特别是对于处理高维数据。实际上,它使您能够在较低维的数据结构(如Series (1d)和DataFrame (2d))中存储和操作具有任意维数的数据。
在本节中,我们将展示“分层”索引的确切含义,以及它如何与上面和前面几节中描述的所有panda索引功能集成。稍后,在讨论对数据进行分组、旋转和重塑时,我们将展示一些重要的应用程序,以说明它如何帮助结构化数据以便进行分析。
一、创建多重索引(分层索引)对象
多索引对象是标准索引对象的层次模拟对象,标准索引对象通常在pandas对象中存储axis标签。您可以将MultiIndex看作元组数组,其中每个元组都是唯一的。可以从数组列表(使用MultiIndex.from_arrays())、元组数组(使用MultiIndex.from_tuples())、交叉迭代集(使用MultiIndex.from_product())或DataFrame(使用MultiIndex.from_frame())创建多索引。当向索引构造函数传递一组元组时,它将尝试返回一个多索引。下面的示例演示了初始化多索引的不同方法。
import pandas as pd
import numpy as np
arrays = [['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],\
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']]
tuples = list(zip(*arrays))
tuples
''' [('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')] '''
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
''' MultiIndex([('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')], names=['first', 'second']) '''
s = pd.Series(np.random.randn(8), index=index)
s
''' first second bar one 0.606254 two -1.193545 baz one 1.226008 two 0.486978 foo one 1.469800 two 0.338351 qux one -0.892168 two -0.650476 dtype: float64 '''
当你想要两个迭代中的每一对元素时,使用MultiIndex.from_product()方***更容易:
这种貌似是最简单的哇,记住pd.MultiIndex.from_product
iterables = [['bar', 'baz', 'foo', 'qux'], ['one', 'two']]
pd.MultiIndex.from_product(iterables, names=['first', 'second'])
''' MultiIndex([('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')], names=['first', 'second']) '''
您还可以使用MultiIndex.from_frame()方法直接从一个DataFrame构造一个多索引。这是MultiIndex.to_frame()的补充方法。
*作者感觉这种是最麻烦的,不过挺检验对多维数组的掌握,建议手打一下 *
df = pd.DataFrame([['bar', 'one'], ['bar', 'two'],['baz', 'one'],['baz', 'two'], ['foo', 'one'], ['foo', 'two'], ['qux', 'one'],['qux', 'two']], columns=['first', 'second'])
pd.MultiIndex.from_frame(df)
''' MultiIndex([('bar', 'one'), ('bar', 'two'), ('baz', 'one'), ('baz', 'two'), ('foo', 'one'), ('foo', 'two'), ('qux', 'one'), ('qux', 'two')], names=['first', 'second']) '''
为了方便,你可以直接将数组列表传递到Series或DataFrame来自动构造一个多索引:
arrays = [np.array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux']),
np.array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'])]
arrays
''' [array(['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'], dtype='<U3'), array(['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two'], dtype='<U3')] '''
s = pd.Series(np.random.randn(8), index=arrays) # 创建耽搁Series试试
s
''' bar one 0.042885 two 1.075552 baz one -0.437966 two 0.624236 foo one 0.101495 two 0.639600 qux one -0.260703 two -0.881295 dtype: float64 '''
df = pd.DataFrame(np.random.randn(8,4), index=arrays)
df
''' 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 '''
所有的多索引构造函数都接受一个names参数,该参数存储级别本身的字符串名称。如果没有提供姓名,则不会分配:
df.index.names
''' FrozenList([None, None]) '''
这个索引可以返回pandas对象的任何轴,索引的级别由您决定:
df = pd.DataFrame(np.random.randn(3,8),index=['A', 'B', 'C'], coolums=index)
df
''' 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 '''
df = pd.DataFrame(np.random.randn(6,6), index=index[:6], columns=index[:6])
df
''' first bar baz foo second one two one two one two first second bar one -0.410001 -0.078638 0.545952 -1.219217 -1.226825 0.769804 two -1.281247 -0.727707 -0.121306 -0.097883 0.695775 0.341734 baz one 0.959726 -1.110336 -0.619976 0.149748 -0.732339 0.687738 two 0.176444 0.403310 -0.154951 0.301624 -2.179861 -1.369849 foo one -0.954208 1.462696 -1.743161 -0.826591 -0.345352 1.314232 two 0.690579 0.995761 2.396780 0.014871 3.357427 -0.317441 '''
我们已经“分散”了更高级别的索引,以使控制台输出对你来说更容易一些。注意索引的显示方式可以通过pandas.set_options()中的multi_sparse选项来控制:
元组是标签的必备之选
pd.Series(np.random.randn(8), index=tuples)
''' (bar, one) 0.146193 (bar, two) 0.011110 (baz, one) 0.698768 (baz, two) 0.277018 (foo, one) -0.014839 (foo, two) -0.348363 (qux, one) 0.680304 (qux, two) 0.299718 dtype: float64 '''
多索引很重要的原因是,它允许您执行分组、选择和重塑操作,我们将在下面和文档的后续部分中描述这些操作。正如您将在后面几节中看到的,您会发现自己使用分层索引的数据,而无需自己显式地创建多索引。但是,当从文件加载数据时,您可能希望在准备数据集时生成自己的多索引。
#########################################################
写在最后:
自己和朋友成立了一个工作室——图灵数据科学工作室(VX:DataUpward):
一是想和大家交个朋友;
二是想帮助朋友们跳过我们遇到的坑,尽快找到解决办法。
======================================================
工作室的运行也需要付出各种成本,“活下去”是我们的当务之急,如果大家有 :
- 数据分析(报告);
- 商业数据调研;
- 数据可视化展示;
- 数据爬虫;
- -数据模型开发;
- 机器学习算法挖掘
- …
也欢迎和我们工作室开展合作~