【数据处理包Pandas】多级索引的创建及使用

news2025/1/10 13:48:51

目录

    • 一、元组作为一级索引
      • (一)示例1
      • (二)示例2
    • 二、引入多级索引
      • (一)多级索引的创建
      • (二)多级索引中的数学选取


首先,导入 NumPy 库和 Pandas 库。

import numpy as np
import pandas as pd

一、元组作为一级索引

如果想产生如下图所示的学生成绩表:

在这里插入图片描述
因为 DataFrame 的行索引/列索引要求是不可变的,因此考虑使用元组做索引是很自然的选择。

s_index = [(2016,1),(2016,2),(2017,1),(2017,2)]
s_columns = [('王亮','语文'),('王亮','数学'),('王亮','英语'),('李海','语文'),('李海','数学'),('李海','英语'),('富强','语文'),('富强','数学'),('富强','英语')]
scores = pd.DataFrame(np.random.randint(60,100,(4,9)),index=s_index,columns=s_columns)
scores

在这里插入图片描述

上述由元组构成的行索引/列索引的缺点是使用不够方便,举例说明如下:

(一)示例1

使用元组索引查询时,对 Series 和 DataFrame 的操作不统一,后者需要对元组索引额外加中括号,而前者不用!

1、查询王亮的数学成绩

# 查询王亮的数学成绩
scores[('王亮','数学')]

在这里插入图片描述

2、查询2017年第一学期的成绩

# 查询2017年第一学期的成绩
scores.loc[(2017,1)]---出错!相当于scores.loc[2017,1],此时会把2017看成行索引,1看成列索引,而行索引没有2017

对于 DataFrame,应该在元组的外面再加一层中括号,写成:

scores.loc[[(2017,1)]]

在这里插入图片描述

当然用位置标签是最简单的:

scores.iloc[2,:]

在这里插入图片描述

3、查询王亮2017第1学期的成绩

如果用 DataFrame 直接做查询,则表示行索引和列索引的元组外都要多加一层中括号,需要写成:

scores.loc[[(2017,1)],[('王亮','数学')]]

在这里插入图片描述

但是对于 Series,则无需在元组外面加一层中括号,例如,先得到 Series 再用元组索引可写成:

scores[('王亮','数学')][(2017,1)]

直接使用位置标签:

scores.iloc[2,1]
69

(二)示例2

查询语文成绩时,需要写循环,无法使用切片中的冒号(:)语法,不太方便。

for col in scores.columns:
    if col[1]=='语文':
        print(scores[col])

在这里插入图片描述

上述例子说明:把元组用作单级索引来表示多个维度的信息,不是一个很好的选择!

二、引入多级索引

(一)多级索引的创建

MultiIndex 对象是 Pandas 标准 Index 的子类,由它来表示多层索引业务。 可以将 MultiIndex 视为一个元组对数组,其中每个元组对都是唯一的。

创建主要有三个相关的函数:from_tuples、from_arrays和from_product,它们都是pd.MultiIndex类的方法

1、使用pd.MultiIndex.from_tuples创建 MultiIndex 对象和 DataFrame 对象

t1 = pd.MultiIndex.from_tuples(s_index)
t1
MultiIndex(levels=[[2016, 2017], [1, 2]],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
t2 = pd.MultiIndex.from_tuples(s_columns)
t2
MultiIndex(levels=[['富强', '李海', '王亮'], ['数学', '英语', '语文']],
           labels=[[2, 2, 2, 1, 1, 1, 0, 0, 0], [2, 0, 1, 2, 0, 1, 2, 0, 1]])
scores = pd.DataFrame(np.random.randint(60,100,(4,9)),index=t1,columns=t2)
scores

在这里插入图片描述

2、使用pd.MultiIndex.from_arrays创建 MultiIndex 对象和 DataFrame 对象

a1 = pd.MultiIndex.from_arrays([[2016,2016,2017,2017],[1,2,1,2]])   # 两级索引都放在列表中,属于花式索引的写法
a1
MultiIndex(levels=[[2016, 2017], [1, 2]],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]])
a2 = pd.MultiIndex.from_arrays([['王亮','王亮','王亮','李海','李海','李海','富强','富强','富强'],
                                ['语文','数学','英语','语文','数学','英语','语文','数学','英语']])   
a2
MultiIndex(levels=[['富强', '李海', '王亮'], ['数学', '英语', '语文']],
           labels=[[2, 2, 2, 1, 1, 1, 0, 0, 0], [2, 0, 1, 2, 0, 1, 2, 0, 1]])
scores = pd.DataFrame(np.random.randint(60,100,(4,9)),index=a1,columns=a2)
scores

在这里插入图片描述

3、使用pd.MultiIndex.from_product创建 MultiIndex 对象和 DataFrame 对象(推荐!)

r_index = pd.MultiIndex.from_product([[2016,2017],[1,2]],names=['年份','学期'])
r_index
MultiIndex(levels=[[2016, 2017], [1, 2]],
           labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
           names=['年份', '学期'])
c_index = pd.MultiIndex.from_product([['王亮','李海','富强'],['语文','数学','英语']],names=['姓名','课程'])
c_index   # 下面显示的levels的内容是系统已经拍过序的
MultiIndex(levels=[['富强', '李海', '王亮'], ['数学', '英语', '语文']],
           labels=[[2, 2, 2, 1, 1, 1, 0, 0, 0], [2, 0, 1, 2, 0, 1, 2, 0, 1]],
           names=['姓名', '课程'])
np.random.seed(666)
scores = pd.DataFrame(np.random.randint(60,100,(4,9)),index=r_index,columns=c_index)
scores

在这里插入图片描述

(二)多级索引中的数学选取

1、基于列索引选取数据

# 基于列的第1层索引选取单列
scores['富强']

在这里插入图片描述

# 基于列的第1层索引选取多列,需要使用花式索引
scores[['富强','王亮']]

在这里插入图片描述
补充说明:

排序时默认按第一个字符的 Unicode 编码顺序升序排序。
查看一个字符的十进制 Unicode 编码:ord(字符);查看一个字符的十六进制 Unicode 编码:hex(ord(字符))。

  • level 0级的排序:富、李、王的十进制Unicode编码分别是23500、26446和29579
  • level 1级的排序:数、英和语十进制Unicode编码分别是25968、33521和35821

sort_index()没有指明对哪个级别的列索引排序,默认对两级列索引都做了排序。如果只对level 0级的列索引排序,则应指明参数level=0;要对level 0级升序,而level 1级降序,则应该额外使用参数level=[0,1],ascending=[True,False]

scores.sort_index(axis=1,inplace=True)   # axis=1指明对列索引按升序排列,注意inplace=True后才能看到排序结果  
scores

在这里插入图片描述

# axis=0指明对行索引排序
scores.sort_index(axis=0,inplace=True,level=[0,1],ascending=[False,True])
scores

在这里插入图片描述

# 基于列的第2层索引选取单独1列
scores.loc[:,(slice(None),'语文')]

其中的:表示行索引是任意的,切片slice(None)表示第 0 级列索引是任意的。
注意:元组中不允许使用:,因此用slice(None)代替。
说明:多级索引的切片操作要求必须先对索引排序,因此才有上面的sort_index()函数调用。

在这里插入图片描述

# 基于列的第2层索引选取多列
scores.loc[:,(slice(None),['语文','数学'])] 

其中的花式索引['语文','数学']表示选取 level 1 级列索引是语文和数学的两列。

在这里插入图片描述

# 同时基于列的第1层和第2层索引选取数据
scores['李海','语文']   # 等价于scores[('李海','语文')]

注意:虽然scores[('李海','语文')]可以,但不能使用scores[(slice(None),'语文')]选取所有的语文成绩。而只能通过scores.loc[:,(slice(None),'语文')]选取所有的语文成绩。

在这里插入图片描述

小结:无论基于行索引还是列索引选取数据,只要没指定最高级索引,则必须使用.loc[行索引,列索引]的形式。

2、基于行索引选取数据

基于行索引选取数据,必须使用.loc[]的形式。

# 基于行的单个第1层索引值选取数据
scores.loc[2017]

在这里插入图片描述

# 基于行的多个第1层索引值选取数据
scores.loc[[2017,2016]]

在这里插入图片描述

# 基于行的单个第2层索引值选取数据
scores.loc[(slice(None),2),:]    # 不能写成scores.loc[(slice(None),2)]或scores.loc[slice(None),2]的形式

在这里插入图片描述

# 基于行的多个第2层索引值选取数据
scores.loc[(slice(None),[1,2]),:]   # 不能写成scores.loc[(slice(None),1:2),:],元组中不支持:进行切片操作

在这里插入图片描述

# 同时基于行的第1层和第2层索引选取数据
scores.loc[2016,2]   # 等价于scores.loc[(2016,2)]或scores.loc[(2016,2),:],表示元组的括号此时可以去掉
姓名  课程
富强  数学    72
    英语    75
    语文    78
李海  数学    99
    英语    65
    语文    76
王亮  数学    74
    英语    93
    语文    88
Name: (2016, 2), dtype: int32
# 查看2016年所有学生的数学和英语成绩
scores.loc[2016,(slice(None),['数学','英语'])]  #*1*
# 查看第2学期的全部数据
scores.loc[(slice(None),2),:]  #*2*    不能写成scores.loc[(slice(None),2)]或scores.loc[slice(None),2]的形式
# 查看李海同学的语文成绩
scores['李海','语文']  #*3* 等价于scores.loc[:,('李海','语文')] 或scores[('李海','语文')] 
# 查看2017年第1学期的成绩
scores.loc[2017,1]   #*4* 等价于scores.loc[(2017,1),:]或scores.loc[(2017,1)]

以#1——#4的语句为例来小结多级索引下的数据选取方式:

1、选取数据的通用形式:

(1)通用写法是:df.loc[(行索引),(列索引)],例如#1处;
(2)其中行/列索引分别构成元组,并且从左到右,索引级别依次下降,相邻级别间用逗号分隔;
(3)未指明的高级别行/列索引需要用slice(None)表示取任意值(例如#1处的第1级列索引);未指明的低级别索引可以不写(例如#1处的第2级行索引);如果同级别的索引有多个(例如#1处的第2级列索引),需要用花式索引而不能使用切片(元组不支持冒号:);

2、选取数据的简化形式:

(1)当只涉及列索引元组并且其中不包含slice(None)时,行索引元组可以用冒号(:)简化,写成df.loc[:,(列索引)];或者进一步简化成df[列索引](即loc行选择器和表示元组的圆括号都可以省略,例如#3处)
(2)当只涉及行索引元组并且其中不包含slice(None)时,列索引元组可以用冒号(:)简化,写成df.loc[(行索引),:];或者进一步简化成df.loc[行索引](即表示元组的圆括号也省略了,例如#4处);注意:loc行选择器不能省略,因为只要包含行索引,一定要使用行选择器loc或iloc,而选择列索引则不需要!
(3)无论行/列索引,只要有一个元组中包含slice(None),就不能使用上述简化形式,而必须使用通用形式(#1和#2处)

注意:为了在多级索引的中括号[]中可以使用切片(即使用冒号:),需要先使用sort_index()函数对索引进行排序。

上面的结论可以把前面的所有例子都归纳在其中!

# 多级索引中的行/列索引使用元组表示法,不方便之处在于对于元组内部的索引无法使用切片,为此引入IndexSlice对象
idx = pd.IndexSlice
# 用idx改写上面的*1*和#*2*语句
# 查看2016年所有学生的数学和英语成绩
scores.loc[2016,idx[:,['数学','英语']]]  #*1*  用:替代了slice(None)
scores.loc[2016,idx[:,'数学':'英语']]  # 与上面等价,用第2级列索引上的切片('数学':'英语')替代了上面的花式索引

在这里插入图片描述

# 查看第2学期的全部数据
scores.loc[idx[:,2],:]   #*2*

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1566311.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MTU/TCPMSS/VLAN/ACCESS/TRUNK/HYBRID

MTU RFC标准定义以太网的默认MTU值为1500 最小64字节是为了保证最极端的冲突能被检测到,64字节是能被检测到的最小值;最大不超过1518字节是为了防止过长的帧传输时间过长而占用共享链路太长时间导致其他业务阻塞。所以规定以太网帧大小为64~1518字节&am…

Day17-【Java SE进阶】特殊文本文件、日志技术

一、特殊文本文件 为什么要用这些特殊文件? 存储多个用户的:用户名、密码 存储有关系的数据,做为系统的配置文件做为信息进行传输 日志技术 把程序运行的信息,记录到文件中,方便程序员定位bug、并了解程序的执行情…

代码块的理解

如果成员变量想要初始化的值不是一个硬编码的常量值,而是需要通过复杂的计算或读取文件、或读取运行环境信息等方式才能获取的一些值,该怎么办呢?此时,可以考虑代码块(或初始化块)。 代码块(或初始化块)的作…

Harmony创建Page省事小技巧

在创建Page页面时,选择ArkTS File时,创建的文件不会自动生成基础代码,也不会自动在main_page.json中自动进行注册,如何解决问题呢,其实很简单创建Page页面时选择Page项后就会创建Page文件,创建完的页面会自…

基于深度学习的铁轨缺陷检测系统(网页版+YOLOv8/v7/v6/v5代码+训练数据集)

摘要:本文深入研究了基于YOLOv8/v7/v6/v5的铁轨缺陷检测系统。核心技术上,文章采用了最先进的YOLOv8,并整合了YOLOv7、YOLOv6、YOLOv5算法,进行了性能指标的对比分析。文中详细阐述了国内外铁轨缺陷检测的研究现状、数据集处理方法…

封装一个vue3的公共组件

在Vue 3中,封装公共组件的场景包括但不限于以下几种情况: 重复使用的组件:如果你发现某个组件在多个地方重复使用,那么将其封装成公共组件是很有意义的。比如,页面中的各种表单控件(输入框、下拉框、日期选…

超级AI大脑产品架构图解析

一、概述 超级AI大脑是一个集成了先进的人工智能技术,为用户提供全方位、智能化的服务的产品。其产品架构图设计旨在清晰展现其技术层次、功能模块与业务流程,以确保用户能够高效、便捷地利用该产品。 二、技术层次 基础设施层: 服务器&…

大模型学习笔记八:手撕AutoGPT

文章目录 一、功能需求二、演示用例三、核心模块流程图四、代码分析1)Agent类目录创建智能体对象2)开始主流程3)在prompt的main目录输入主prompt和最后prompt4)增加实际的工具tools 一、功能需求 目的 设计一个 Agent&#xff0c…

yolov8姿态识别与绘制

YOLOv8姿态检测是一种基于深度学习的计算机视觉技术,用于识别图像或视频中人体的姿态。作为YOLO系列算法的最新版本,YOLOv8在姿态检测任务上展现出了卓越的性能和效率。以下将详细介绍YOLOv8姿态检测的原理、特点、应用以及训练过程。 一、YOLOv8姿态检…

快消企业数字化转型实战解析:探寻未来增长新动力

2024年,快消行业正站在数字化转型的风口浪尖。 “今年是过去十年最差的一年,但却可能是未来十年最好的一年。”这句话几乎成为了今年的流行语。 但是这句话是情绪,不是事实。未来十年,中国会成为全球最大的消费品市场&#xff0…

CSS基础选择器 小案例复习(画三个小盒子)

(大家好,前面我们学习了基础的选择器,俗话说:温故而知新。所以今天我们将通过小案例来复习前面学过的小知识点。另,十分感谢大家对我文章的支持❤️) 通过这个案例复习两个地方: 类选择器的使用…

AJAX —— 学习(三)

目录 一、jQuery 中的 AJAX (一)get 方法 1.语法介绍 2.结果实现 (二)post 方法 1.语法介绍 2.结果实现 (三)通用型的 AJAX 方法 1.语法介绍 2.结果实现 二、AJAX 工具库 axios (…

js 基础知识 forEach 和 map 的区别,及 map 不加 return 返回什么

问题一:forEach 和 map 之间的区别: 1、forEach 不返回新数组,map 返回新数组,其中包含回调函数的返回值。 2、用途:如果只想要遍历数组并对每个元素执行某些操作而不产生新数组,那么应该使用 forEach&am…

全网最强JavaWeb笔记 | 万字长文爆肝JavaWeb开发——day04_Maven入门

万字长文爆肝黑马程序员2023最新版JavaWeb教程。这套教程打破常规,不再局限于过时的老套JavaWeb技术,而是与时俱进,运用的都是企业中流行的前沿技术。笔者认真跟着这个教程,再一次认真学习一遍JavaWeb教程,温故而知新&…

ETL工具-nifi干货系列 第八讲 处理器PutDatabaseRecord 写数据库(详细)

1、本节通过一个小例子来讲解下处理器PutDatabaseRecord,该处理器的作用是将数据写入数据库。 如下流程通过处理器GenerateFlowFile 生成数据,然后通过处理器JoltTransformJSON转换结构,最后通过处理器PutDatabaseRecord将数据写入数据库。如…

软件架构风格_4.虚拟机体系结构风格

虚拟机体系结构风格的基本思想是人为构建一个运行环境,在这个环境之上,可以解析与运行自定义的一些语言,这样来增加架构的灵活性。虚拟机体系结构风格主要包括解释器风格和规则系统风格。 1.解释器体系结构风格 一个解释器通常包括完成解释工…

首个适配Visual Studio平台的国产智能编程助手CodeGeeX正式上线!C#程序员必备效率神器!

CodeGeeX是一款免费的智能编程助手。 继CodeGeeX在Visual Studio Code、JetBrains IDEs全家桶、HBuilderX、deepin-IDE等主流IDE中上线后,用户呼声最高的Visual Studio平台的适配插件产品也正式推出上线了!成为首个适配Visual Studio平台的国产智能编程…

docker导出导入镜像

docker导出镜像 查看要导出的镜像 docker images主要有两列 REPOSITORY TAG 导出命令 导出公式 docker save -o xxxx.tar REPOSITORY:TAG例子 docker save -o minio.tar minio/minio:latestminio/minio:latest可以使用image id代替,但是使用image id会导致导…

笔记: JavaSE day15 笔记

第十五天课堂笔记 数组 可变长参数★★★ 方法 : 返回值类型 方法名(参数类型 参数名 , 参数类型 … 可变长参数名){}方法体 : 变长参数 相当于一个数组一个数组最多只能有一个可变长参数, 并放到列表的最后parameter : 方法参数 数组相关算法★★ 冒泡排序 由小到大: 从前…

基于springboot实现校园周边美食探索及分享平台系统项目【项目源码+论文说明】

基于springboot实现园周边美食探索及分享平台系统演示 摘要 美食一直是与人们日常生活息息相关的产业。传统的电话订餐或者到店消费已经不能适应市场发展的需求。随着网络的迅速崛起,互联网日益成为提供信息的最佳俱渠道和逐步走向传统的流通领域,传统的…