Pandas提供了Panel和Panel4D对象解决三维和四维数据的处理需求,但更常用的还是分层索引。分层索引是Pandas的重要特性,允许我们在一个轴向上拥有多个索引层级,它提供了一种在更低维度的形式中处理更高维度数据的方式。也就是如何用Series、DataFrame处理三维、四维等等高维度的数据。
比如有下面的数据:
In [168]: s = pd.Series(np.random.randn(9), index=[['a', 'a', 'a', 'b', 'b', 'c', 'c', 'd', 'd'], [1, 2, 3, 1, 3, 1, 2, 2, 3]]) In [169]: s Out[169]: a 1 0.283490 2 0.295529 3 0.277676 b 1 0.487573 3 0.091161 c 1 0.285157 2 -0.806851 d 2 -0.287969 3 -0.696511 dtype: float64 In [170]: s.index Out[170]: MultiIndex(levels=[['a', 'b', 'c', 'd'], [1, 2, 3]], labels=[[0, 0, 0, 1, 1, 2, 2, 3, 3], [0, 1, 2, 0, 2, 0, 1, 1, 2]])
MultiIndex就是一个分层索引对象,在打印的时候会进行规整的美化。
下面看下一些基本的操作:
In [171]: s['b'] Out[171]: 1 0.487573 3 0.091161 dtype: float64 In [172]: s['b':'c'] Out[172]: b 1 0.487573 3 0.091161 c 1 0.285157 2 -0.806851 dtype: float64 In [173]: s.loc[['b','d']] Out[173]: b 1 0.487573 3 0.091161 d 2 -0.287969 3 -0.696511 dtype: float64 In [174]: s.loc['b','d'] # 这样不可以 --------------------------------------------------------------------------- IndexingError Traceback (most recent call last) IndexingError: Too many indexers In [175]: s.loc['b',1] # 但是这样可以 Out[175]: 0.48757273896298425 In [176]: s.loc[:, 2] # 或者这样 Out[176]: a 0.295529 c -0.806851 d -0.287969 dtype: float64 tup = []
我们还可以这样来生成MultiIndex,请体会它的不同之处:
In [3]: tup = [('beijing',2000),('beijing',2019), ...: ('shanghai',2000),('shanghai',2019), ...: ('guangzhou',2000),('guangzhou',2019)] In [4]: values = [10000,100000,6000,60000,4000,40000] In [7]: index = pd.MultiIndex.from_tuples(tup) # 利用元组生成MultiIndex In [8]: sss = pd.Series(values, index=index) # 提供一个MultiIndex作为索引 In [9]: sss Out[9]: beijing 2000 10000 2019 100000 shanghai 2000 6000 2019 60000 guangzhou 2000 4000 2019 40000 dtype: int64
更多的创建MultiIndex的方法还有:
生成MultiIndex对象后,就可以将这些对象作为参数,在创建Series或者DataFrame时传递给index。或者通过reindex方法更新已有的Series/DataFrame索引。
分层索引在重塑数据和数组透视表中非常重要。比如,我们可以使用unstack方法将数据在DataFrame中重新排列,也就是展开:
In [178]: s.unstack() Out[178]: 1 2 3 a 0.283490 0.295529 0.277676 b 0.487573 NaN 0.091161 c 0.285157 -0.806851 NaN d NaN -0.287969 -0.696511 In [179]: s.unstack().stack() # 反操作stack Out[179]: a 1 0.283490 2 0.295529 3 0.277676 b 1 0.487573 3 0.091161 c 1 0.285157 2 -0.806851 d 2 -0.287969 3 -0.696511 dtype: float64
对于DataFrame对象,每个轴都可以有分层索引,给index或columns提供一个多维数组,就可以分层:
In [3]: df = pd.DataFrame(np.arange(12).reshape((4, 3)), ...: index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]], ...: columns=[['Ohio', 'Ohio', 'Colorado'], ...: ['Green', 'Red', 'Green']]) In [4]: df Out[4]: Ohio Colorado Green Red Green a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11
可以给分层索引自定义名字:
In [5]: df.index.names Out[5]: FrozenList([None, None]) In [6]: df.index.names = ['key1','key2'] In [7]: df.columns.names Out[7]: FrozenList([None, None]) In [8]: df.columns.names = ['state','color'] In [9]: df Out[9]: state Ohio Colorado color Green Red Green key1 key2 a 1 0 1 2 2 3 4 5 b 1 6 7 8 2 9 10 11 In [10]: df['Ohio'] Out[10]: color Green Red key1 key2 a 1 0 1 2 3 4 b 1 6 7 2 9 10