本系列文章配套代码获取有以下三种途径:
-
可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):
https://returu.github.io/Python_Data_Analysis/lab/index.html
-
也可以通过百度网盘获取,需要在本地配置代码运行环境,环境配置可以查看【Python基础】2.搭建Python开发环境:
链接:https://pan.baidu.com/s/1MYkeYeVAIRqbxezQECHwcA?pwd=mnsj
提取码:mnsj
-
前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Data_Analysis
根据《Python for Data Analysis 3rd Edition》翻译整理
—————————————————–
分层索引是 pandas 的一个重要特性,它使你能够在一个轴上拥有多个(两个或更多)索引级别。另一种思考方式是,它提供了一种以低维形式处理高维数据的方法。
1.分层索引:
1.1 Series:
让我们从一个简单的例子开始:创建一个以列表的列表或数组作为索引的Series。
1>>> data = pd.Series(np.random.randn(9),index=[['android','android','android','ios','ios','wp','wp','symbian','symbian'],['htc','google','huawei','iphone6','iphone7','htc','Nokia','Nokia','LG']])
2>>> data
3android htc 0.010561
4 google -0.704215
5 huawei 0.154302
6ios iphone6 -0.695034
7 iphone7 -0.724016
8wp htc -0.978071
9 Nokia 0.327960
10symbian Nokia 0.221268
11 LG -0.426582
12dtype: float64
可以看到的上面例子是一个以 MultiIndex 作为其索引的 Series 的美化视图。索引显示中的“间隙”表示“使用正上方的标签”。
1>>> data.index
2MultiIndex([('android', 'htc'),
3 ('android', 'google'),
4 ('android', 'huawei'),
5 ( 'ios', 'iphone6'),
6 ( 'ios', 'iphone7'),
7 ( 'wp', 'htc'),
8 ( 'wp', 'Nokia'),
9 ('symbian', 'Nokia'),
10 ('symbian', 'LG')],
11 )
分层索引也称为部分索引,允许我们简洁的选择出数据的子集。
1>>> data["android"]
2htc 0.010561
3google -0.704215
4huawei 0.154302
5dtype: float64
6
7# 如果试图索引一些没有完全 lexsorted 的索引会报错,需要先进行第二部分提到的重排序操作
8>>> data["android":"symbian"]
9UnsortedIndexError: 'Key length (1) was greater than MultiIndex lexsort depth (0)'
10
11
12>>> data.loc[["android","symbian"]]
13android htc 0.010561
14 google -0.704215
15 huawei 0.154302
16symbian Nokia 0.221268
17 LG -0.426582
18dtype: float64
在内部层级中进行选择也是被允许的。
1>>> data.loc[: , "huawei"]
2android 0.154302
3dtype: float64
使用unstack()方法可以将数据在DataFrame中重新排列,使得分层索引在重塑数据和数组透视表操作中经常使用。与unstack()相对应的是stack()方法。
1>>> data.unstack()
2 LG Nokia google htc huawei iphone6 iphone7
3android NaN NaN -0.704215 0.010561 0.154302 NaN NaN
4ios NaN NaN NaN NaN NaN -0.695034 -0.724016
5symbian -0.426582 0.221268 NaN NaN NaN NaN NaN
6wp NaN 0.327960 NaN -0.978071 NaN NaN NaN
7
8>>> data.unstack().stack()
9android google -0.704215
10 htc 0.010561
11 huawei 0.154302
12ios iphone6 -0.695034
13 iphone7 -0.724016
14symbian LG -0.426582
15 Nokia 0.221268
16wp Nokia 0.327960
17 htc -0.978071
18dtype: float64
1.2 DataFrame:
在DataFrame中,每个轴都可以拥有分层索引,并且分层的层级可以有名称。如果有名称将会显示在控制台输出中。
1>>> data = pd.DataFrame(np.arange(12).reshape((4, 3)),
2... index=[["a", "a", "b", "b"], [1, 2, 1, 2]],
3... columns=[["android", "android", "ios"],["HTC", "Google", "iphone"]])
4
5>>> data
6 android ios
7 HTC Google iphone
8a 1 0 1 2
9 2 3 4 5
10b 1 6 7 8
11 2 9 10 11
12
13>>> data.index.names = ["key1" ,"key2"]
14>>> data.columns.names = ["platform","device"]
15
16>>> data
17platform android ios
18device HTC Google iphone
19key1 key2
20a 1 0 1 2
21 2 3 4 5
22b 1 6 7 8
23 2 9 10 11
可以通过访问其 nlevels 属性来查看索引有多少级别。
1>>> data.index.nlevels
22
同样,在DataFrame中也可以通过列索引选择列中的数据组。
1>>> data["android"]
2device HTC Google
3key1 key2
4a 1 0 1
5 2 3 4
6b 1 6 7
7 2 9 10
一个MultiIndex可以自己创建,然后复用;前面 DataFrame 中具有级别名称的列也可以这样创建:
1>>> pd.MultiIndex.from_arrays([["android","android","ios"],["HTC","Google","iphone"]],
2... names=["platform","device"])
3MultiIndex([('android', 'HTC'),
4 ('android', 'Google'),
5 ( 'ios', 'iphone')],
6 names=['platform', 'device'])
有时,你可能需要重新排列轴上的层级顺序或按某个特定层级中的值对数据进行排序。
swaplevel
方法接收两个层级的序号或名称,返回一个层级互换的新对象(但数据未更改)。
1>>> data
2platform android ios
3device HTC Google iphone
4key1 key2
5a 1 0 1 2
6 2 3 4 5
7b 1 6 7 8
8 2 9 10 11
9
10>>> data.swaplevel('key1','key2')
11platform android ios
12device HTC Google iphone
13key2 key1
141 a 0 1 2
152 a 3 4 5
161 b 6 7 8
172 b 9 10 11
18
19>>> data.swaplevel(0,1)
20platform android ios
21device HTC Google iphone
22key2 key1
231 a 0 1 2
242 a 3 4 5
251 b 6 7 8
262 b 9 10 11
sort_index
方法可以在指定层级(通过设置level选项)对数据进行排序操作。
1>>> data.sort_index(level=1)
2platform android ios
3device HTC Google iphone
4key1 key2
5a 1 0 1 2
6b 1 6 7 8
7a 2 3 4 5
8b 2 9 10 11
9
10>>> data.swaplevel(0,1).sort_index(level=0)
11platform android ios
12device HTC Google iphone
13key2 key1
141 a 0 1 2
15 b 6 7 8
162 a 3 4 5
17 b 9 10 11
3.按层级进行汇总统计:
通过设置level选项可以按层级进行描述性和汇总性统计操作,另外可以通过设置axis指定操作的轴。
1>>> data.groupby("key1").sum()
2platform android ios
3device HTC Google iphone
4key1
5a 3 5 7
6b 15 17 19
7
8>>> data.groupby(level="platform",axis=1).sum()
9platform android ios
10key1 key2
11a 1 1 2
12 2 7 5
13b 1 13 8
14 2 19 11
15
16# 该方式会在未来版本中废弃
17>>> data.sum(level="key1")
18<stdin>:1: FutureWarning: Using the level keyword in DataFrame and Series aggregations is deprecated and will be removed in a future version. Use groupby instead. df.sum(level=1) should use df.groupby(level=1).sum().
19platform android ios
20device HTC Google iphone
21key1
22a 3 5 7
23b 15 17 19
想要使用 DataFrame 中的一个或多个列作为行索引并不罕见;或者,你可能希望将行索引移动到 DataFrame 的列中。
这是一个示例 DataFrame:
1>>> df = pd.DataFrame({"key1":["a", "b", "b", "a", "b", "a"],
2... "key2":range(6),
3... "key3":["one", "one", "two", "one", "one", "two"],
4... "key4":[11, 22, 33, 22, 22, 33]})
5>>> df
6 key1 key2 key3 key4
70 a 0 one 11
81 b 1 one 22
92 b 2 two 33
103 a 3 one 22
114 b 4 one 22
125 a 5 two 33
DataFrame 的 set_index 函数将使用其一个或多个列作为索引创建一个新的 DataFrame。
1>>> df2 = df.set_index(["key1","key3"])
2>>> df2
3 key2 key4
4key1 key3
5a one 0 11
6b one 1 22
7 two 2 33
8a one 3 22
9b one 4 22
10a two 5 33
默认情况下,列从 DataFrame 中删除,但您可以通过将 drop=False
传递给 set_index 来保留它们。
1>>> df.set_index(["key1","key3"],drop=False)
2 key1 key2 key3 key4
3key1 key3
4a one a 0 one 11
5b one b 1 one 22
6 two b 2 two 33
7a one a 3 one 22
8b one b 4 one 22
9a two a 5 two 33
另一方面,reset_index 与 set_index
相反;层次索引级别被移动到列中。
1>>> df2.reset_index()
2 key1 key3 key2 key4
30 a one 0 11
41 b one 1 22
52 b two 2 33
63 a one 3 22
74 b one 4 22
85 a two 5 33
本篇文章来源于微信公众号: 码农设计师