【基本工具】S02E11 Pandas多级索引的创建方法

0.本集概览

1.带多级索引的Series数据类型
2.多级索引Series对象和DataFrame对象的相互转化
3.带多级索引的DataFrame数据类型
4.多级索引的创建方法
5.多级行索引和多级列索引举例

1.多级索引的Series类型

之前的几集里,我们使用了Series数据类型表示一维数据(即仅有一个索引列),用DataFrame类型数据表示二维数据(即包含行索引和列索引这两维索引数据)。

但是如果是下面这种情况呢?比如我们用Series来表示美国不同的州、不同年份的人口数据,这对Series来说就相当于有了两个索引值:即(州,人口)二维索引,第一反应我们尝试使用元组来表示索引信息:
代码片段:

import pandas as pd
import numpy as np

index = [('California', 2008), ('California', 2018),
         ('New York', 2008), ('New York', 2018),
         ('Texas', 2008), ('Texas', 2018)]
population = [33870000, 37250000,
              18970000, 19370000,
              20850000, 25140000]

pop = pd.Series(population, index=index)
print(pop)

运行结果:

(California, 2008)    33870000
(California, 2018)    37250000
(New York, 2008)      18970000
(New York, 2018)      19370000
(Texas, 2008)         20850000
(Texas, 2018)         25140000
dtype: int64

这是我们第一直觉所采取的方法,但是这种形式在数据的操作上很不方便,比如我们要拿出所有2018年的数据,似乎比较繁琐。

不用着急,Pandas为我们提供了更好、更直观的解决方法,他提供了一个MultiIndex类型,专门用来处理这种多级索引的问题

我们尝试用这种方法做一个示范:
代码片段:

import pandas as pd
import numpy as np

index = [('California', 2008), ('California', 2018),
         ('New York', 2008), ('New York', 2018),
         ('Texas', 2008), ('Texas', 2018)]
mul_index = pd.MultiIndex.from_tuples(index)
print(mul_index)

运算结果:

MultiIndex(levels=[['California', 'New York', 'Texas'], [2008, 2018]],
           labels=[[0, 0, 1, 1, 2, 2], [0, 1, 0, 1, 0, 1]])

我们生成了一个MultiIndex类型的对象,其中levels属性的两个列表元素表示两个索引列里的值,labels里则表示每一个索引列每个位置上对应的是levels相应列表里的第几个元素。

我们用这种方式,重新来构建一个带有多维索引的Series类型数据:
代码片段:

import pandas as pd
import numpy as np

index = [('California', 2008), ('California', 2018),
         ('New York', 2008), ('New York', 2018),
         ('Texas', 2008), ('Texas', 2018)]

mul_index = pd.MultiIndex.from_tuples(index)
population = [33870000, 37250000,
               18970000, 19370000,
               20850000, 25140000]

pop = pd.Series(population, index=mul_index)
print(pop)

运行结果:

California  2008    33870000
            2018    37250000
New York    2008    18970000
            2018    19370000
Texas       2008    20850000
            2018    25140000
dtype: int64

在结果中,我们可以看到,前面两列表示Series的多级索引,第三列是我们的数据,那么回到刚刚的问题,如果此时我们想获取2018年的所有数据,做法就相当简单了:
代码片段:

print(pop[:, 2018])

运行结果:

California    37250000
New York      19370000
Texas         25140000
dtype: int64

简简单单用二维的切片方式就可以处理了。

2.多级Series和普通DataFrame的转换

二维的Series,怎么感觉和DataFrame其实是一回事儿呢?

没错,其实我们把其中的一维索引放到行的位置上,可不就成了一个普通的二维DataFrame对象嘛,而且Pandas里还提供了方法让这二者互相转化。我们还是沿用上面的二维Series对象pop来举个例子:
代码片段:

df_pop = pop.unstack()
print(df_pop)
print(df_pop.stack())

运行结果:

                2008      2018
California  33870000  37250000
New York    18970000  19370000
Texas       20850000  25140000

California  2008    33870000
            2018    37250000
New York    2008    18970000
            2018    19370000
Texas       2008    20850000
            2018    25140000
dtype: int64

unstack( )方法可以使一个带有多级索引的Series转化为一个普通的DataFrame对象,而stack( )方法实现的则是相反方向的操作。

3.多级索引DataFrame类型

既然二维Sereis可以用DataFrame来表示,那干嘛还要费劲去了解这个多级索引?

很简单,因为还有更高维的数据,既然我们可以用一维Sereis来表示二维的数据,那么也可以用Sereis、DataFrame来表示三维甚至是更高维的数据。

比如,我们要表示上述三个州,2008/2018,总人口/18岁以下的人口,我们看到这是三维信息了,怎么样,是不是最终还是逃不掉多级索引?

这次我们使用DataFrame来表示三级索引,用我们之前讲过的DataFrame构造的方法,用字典列表来进行构造:
代码片段:
```
import pandas as pd
import numpy as np

index = [('California', 2008), ('California', 2018),
('New York', 2008), ('New York', 2018),
('Texas', 2008), ('Texas', 2018)]

mul_index = pd.MultiIndex.from_tuples(index)
population = [33870000, 37250000,18970000, 19370000, 20850000, 25140000]
under_18_pop = [9267089, 9284094, 4687374, 4318033, 5906301, 6879014]

pop = pd.Series(population, index=mul_index)
pop_df = pd.DataFrame({'total':pop,

top Created with Sketch.