当前位置: 首页 > article >正文

Python数据分析NumPy和pandas(二十四、数据整理--连接、合并和重塑 之一:分层索引)

在许多应用程序中,数据可能分布在多个文件或数据库中,或者数据的排列方式不利于分析。

下面要学习能帮助我们合并、连接和重新排列数据的工具。首先,学习 pandas 中的分层索引概念,然后逐步深入学习数据合并操作、数据重新排列操作等。

一、分层索引(Hierarchical indexing)

分层索引是 pandas 的一项重要功能,它使我们能够在一个轴上具有多个(两个或以上)索引级别。它为我们提供了一种以较低维形式处理高维数据的方法。以一个简单的示例开始,我们以一个列表或数组作为索引创建一个Series对象:

import numpy as np
import pandas as pd

# 设置一个种子,为了每次运行获取相同的随机值
rng = np.random.default_rng(seed=12345)

data = pd.Series(np.random.uniform(size=9), 
                 index=[["a", "a", "a", "b", "b", "c", "c", "d","d"], [1, 2, 3, 1, 3, 1, 2, 2, 3]])

print(data)

输出结果:

a  1    0.474136
    2    0.025017
    3    0.110308
b  1    0.771097
    3    0.915783
c  1    0.575484
    2    0.790313
d  2    0.090362
    3    0.545744
dtype: float64

从以上输出结果看到的是 Series 的美化视图,其中 MultiIndex 作为其索引。索引显示中的“间隙”表示“使用正上方的标签”。

可以用 data.index 查看这个MultiIndex :

import numpy as np
import pandas as pd

# 设置一个种子,为了每次运行获取相同的随机值
rng = np.random.default_rng(seed=12345)

data = pd.Series(np.random.uniform(size=9), 
                 index=[["a", "a", "a", "b", "b", "c", "c", "d","d"], [1, 2, 3, 1, 3, 1, 2, 2, 3]])

print(data.index)

输出结果:

MultiIndex([('a', 1),
            ('a', 2),
            ('a', 3),
            ('b', 1),
            ('b', 3),
            ('c', 1),
            ('c', 2),
            ('d', 2),
            ('d', 3)],
           )

使用分层索引的部分索引可以很方便的选择数据集的子集。例如:

data['b']  输出

1    0.771097
3    0.915783
dtype: float64

data["b":"c"] 输出:

b  1    0.771097
    3    0.915783
c  1    0.575484
    2    0.790313
dtype: float64

data.loc[["b", "d"]] 输出:

b  1    0.771097
    3    0.915783
d  2    0.090362
    3    0.545744
dtype: float64

我们也可以从 “inner” 索引级别进行选择。下面我从第二个索引级别中选择索引值为 2 对应的元素值。data.loc[:, 2]  输出:

a      0.025017
c      0.790313
d      0.090362
dtype: float64

分层索引在重塑数据和基于组的操作(如形成数据透视表)中起着重要作用。例如,我们可以使用其 unstack() 方法将此数据重新排列到 DataFrame 中,stack()方法是unstack() 逆向操作方法:

import numpy as np
import pandas as pd

# 设置一个种子,为了每次运行获取相同的随机值
rng = np.random.default_rng(seed=12345)

data = pd.Series(np.random.uniform(size=9), 
                 index=[["a", "a", "a", "b", "b", "c", "c", "d","d"], [1, 2, 3, 1, 3, 1, 2, 2, 3]])

print(data.unstack())
print(data.unstack().stack())

data.unstack() 输出:

123
a0.4741360.0250170.110308
b0.771097NaN0.915783
c0.5754840.790313NaN
dNaN0.0903620.545744

data.unstack().stack() 输出:

a  1    0.474136
    2    0.025017
    3    0.110308
b  1    0.771097
    3    0.915783
c  1    0.575484
    2    0.790313
d  2    0.090362
    3    0.545744
dtype: float64

使用 DataFrame,任一轴都可以具有分层索引。同时,分层索引的每一层级可以具有名称,例如:

import numpy as np
import pandas as pd

frame = pd.DataFrame(np.arange(12).reshape((4, 3)), 
                     index=[["a", "a", "b", "b"], [1, 2, 1, 2]], 
                     columns=[["Ohio", "Ohio", "Colorado"], ["Green", "Red", "Green"]])
print(frame)

frame.index.names = ["key1", "key2"]
frame.columns.names = ["state", "color"]

print(frame)

设置names前frame输出:

OhioColorado
GreenRedGreen
a1012
2345
b1678
291011

 设置names后frame输出:

stateOhioColorado
colorGreenRedGreen
key1key2
a1012
2345
b1678
291011

从以上格式化输出我们可以看出,分层索引类似于表格的复杂表头。这些设置的names名称取代了 name 属性,该属性仅用于单级索引。这里要注意的是:索引名称 “state” 和 “color” 不是行标签(frame.index 值)的一部分。

可以通过nlevels属性查看所有有多少层,上面示例中的frame可以这样调用frame.index.nlevels输出:2。

使用部分列索引,可以同样选择列方向的子集。例如:

import numpy as np
import pandas as pd

frame = pd.DataFrame(np.arange(12).reshape((4, 3)), 
                     index=[["a", "a", "b", "b"], [1, 2, 1, 2]], 
                     columns=[["Ohio", "Ohio", "Colorado"], ["Green", "Red", "Green"]])

frame.index.names = ["key1", "key2"]
frame.columns.names = ["state", "color"]

frame.index.nlevels

print(frame["Ohio"])

frame["Ohio"]输出:

colorGreenRed
key1key2
a101
234
b167
2910

MultiIndex 可以自行创建,然后复用。前面的 DataFrame 中具有级别名称的列也可以这样创建:

import numpy as np
import pandas as pd

pd.MultiIndex.from_arrays([["Ohio", "Ohio", "Colorado"], 
                           ["Green", "Red", "Green"]], 
                           names=["state", "color"])

二、对分层级别进行排序和重新排序

有时,我们可能需要重新排列轴上层级的顺序或按一个特定级别中的值对数据进行排序。swaplevel() 方法使用两个级别数字或名称,并返回一个级别互换的新对象(但数据在其他方面保持不变)。例如:

import numpy as np
import pandas as pd

frame = pd.DataFrame(np.arange(12).reshape((4, 3)), 
                     index=[["a", "a", "b", "b"], [1, 2, 1, 2]], 
                     columns=[["Ohio", "Ohio", "Colorado"], ["Green", "Red", "Green"]])

frame.index.names = ["key1", "key2"]
frame.columns.names = ["state", "color"]
frame.index.nlevels

frame_swap = frame.swaplevel("key1", "key2")
print(frame_swap)

输出:

stateOhioColorado
colorGreenRedGreen
key2key1
1a012
2a345
1b678
2b91011

对于排序默认情况下,sort_index 方法使用所有索引级别按字典顺序对数据进行排序,但我们可以通过传递 level 参数来选择仅使用单个级别级别子集进行排序。 例如:

import numpy as np
import pandas as pd

frame = pd.DataFrame(np.arange(12).reshape((4, 3)), 
                     index=[["a", "a", "b", "b"], [1, 2, 1, 2]], 
                     columns=[["Ohio", "Ohio", "Colorado"], ["Green", "Red", "Green"]])

frame.index.names = ["key1", "key2"]
frame.columns.names = ["state", "color"]
frame.index.nlevels

frame_swap = frame.swaplevel("key1", "key2")

print(frame.sort_index(level=1))
print(frame.swaplevel(0, 1).sort_index(level=0))

frame.sort_index(level=1) 输出:

stateOhioColorado
colorGreenRedGreen
key1key2
a1012
b1678
a2345
b291011

frame.swaplevel(0, 1).sort_index(level=0) 输出:

stateOhioColorado
colorGreenRedGreen
key2key1
1a012
b678
2a345
b91011

 注意:如果索引从最外层开始按字典顺序排序,(即调用 sort_index(level=0) 或 sort_index() 的结果),则分层索引对象上的数据选择性能要好得多。

三、按分层级别进行的汇总统计

DataFrame 和 Series 上的许多描述性和摘要性统计信息都有一个 level 参数选项,我们可以通过level指定要在特定轴上聚合的级别。以上面的 DataFrame为例,我们可以按级别对 rows 或 columns 进行聚合:

import numpy as np
import pandas as pd

frame = pd.DataFrame(np.arange(12).reshape((4, 3)), 
                     index=[["a", "a", "b", "b"], [1, 2, 1, 2]], 
                     columns=[["Ohio", "Ohio", "Colorado"], ["Green", "Red", "Green"]])

frame.index.names = ["key1", "key2"]
frame.columns.names = ["state", "color"]
frame.index.nlevels

print(frame.groupby(level="key2").sum())
print(frame.groupby(level="color", axis="columns").sum())

frame.groupby(level="key2").sum() 输出: 

stateOhioColorado
colorGreenRedGreen
key2
16810
2121416

frame.groupby(level="color", axis="columns").sum() 输出: 

colorGreenRed
key1key2
a121
284
b1147
22010

用frame.groupby(level="color", axis="columns").sum()进行汇总,代码运行时会有一个警告FutureWarning,提示groupby方法中使用axis参数已被丢弃,但同样可以执行。这是因为我使用了最新版的pandas库。这行代码可以改为:frame.T.groupby(level="color").sum().T

四、使用 DataFrame 的列进行索引

使用 DataFrame 中的一列或多列作为行索引也是常用的操作;或者,有时候我们想将 行 索引移动到 DataFrame 的列中。DataFrame 的 set_index 函数将使用其一个或多个列作为索引创建新的 DataFrame。默认情况下,这些列将从 DataFrame 中删除,但我们可以通过将 drop=False 传递给 set_index 来保留它们。set_index函数有个逆向操作函数reset_index将分层索引级别移动到列中。我们写个示例:

import numpy as np
import pandas as pd

frame = pd.DataFrame({"a": range(7), "b": range(7, 0, -1),
                      "c": ["one", "one", "one", "two", "two",
                            "two", "two"],
                      "d": [0, 1, 2, 0, 1, 2, 3]})
print(frame)

frame2 = frame.set_index(["c", "d"])
print(frame2)

frame3 = frame.set_index(["c", "d"], drop=False)
print(frame3)

frame4 = frame2.reset_index()
print(frame4)

frame输出:

abcd
007one0
116one1
225one2
334two0
443two1
552two2
661two3

 frame2输出:

ab
cd
one007
116
225
two034
143
252
361

frame3输出:

abcd
cd
one007one0
116one1
225one2
two034two0
143two1
252two2
361two3

 frame4输出:

cdab
0one007
1one116
2one225
3two034
4two143
5two252
6two361

http://www.kler.cn/a/381458.html

相关文章:

  • Jmeter命令监控CPU等指标
  • HiveSQL 中判断字段是否包含某个值的方法
  • 练习LabVIEW第三十八题
  • Python基于TensorFlow实现双向循环神经网络GRU加注意力机制分类模型(BiGRU-Attention分类算法)项目实战
  • 【ArcGIS】绘制各省碳排放分布的中国地图
  • 《AI产品经理手册》——解锁AI时代的商业密钥
  • 51单片机教程(八)- 数码管的静态显示
  • 云轴科技ZStack 联合 OpenCloudOS 完成技术兼容互认证
  • 目标检测YOLO实战应用案例100讲-基于深度学习的人眼视线检测
  • 【云原生开发】如何通过client-go来操作K8S集群
  • 排序算法详细总结
  • 导师双选系统开发新解:Spring Boot技术
  • 练手之基于python的新闻爬虫
  • github.com port 22
  • 基于TRIZ理论的便携式光伏手机充电装置创新
  • 《Linux系统编程篇》消息队列(Linux 进程间通信(IPC))——基础篇
  • docker配置与基础操作
  • Go语言组合和转发
  • 通过自然语言表达你的想法。GitHub Spark让任何人都能使用人工智能,为自己创建软件...
  • Spring Boot环境下的导师双选流程优化
  • 鸿蒙ArkTS中的布局容器组件(Column、Row、Flex、 Stack、Grid)
  • Xfce桌面设置右键菜单:用右键打开VSCode
  • ABAP Git PULL 出错:DDIF_TABLE_PUT
  • Linux基础1
  • Spring-Day5
  • 什么是软件设计模式, 它们⽤于解决什么问题, 它们为什么有效