5.层次化索引
5.1 认识层次化索引
在一个轴方向上有多层索引。如图:
Series和DataFrame均可以实现层次化索引,最常见的方式是在构造方法的index参数中传入一个嵌套列表。
5.1.1 Series
对象层次化索引
例如:
import pandas as pd
mulitindex_series = pd.Series(
[12462, 1546, 1234, 123, 5456, 5554, 33213, 2124],
index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
print(mulitindex_series)
输出为:
河北省 石家庄市 12462
唐山市 1546
邯郸市 1234
秦皇岛市 123
河南省 郑州市 5456
开封市 5554
洛阳市 33213
新乡市 2124
dtype: int64
5.1.2 DataFrame
对象层次化索引
例如:
import pandas as pd
mulitindex_DataFrame = pd.DataFrame(
{'占地面积': [12462, 1546, 1234, 123, 5456, 5554, 33213, 2124]},
index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
print(mulitindex_DataFrame)
输出:
占地面积
河北省 石家庄市 12462
唐山市 1546
邯郸市 1234
秦皇岛市 123
河南省 郑州市 5456
开封市 5554
洛阳市 33213
新乡市 2124
5.2 常用方法
层次化索引除了直接创建之外还可以通过MultiIndex
类的方法构建层次化索引,这个类提供了三种创建层次化索引的方法:
MultiIndex.from_tuples()
:将元组列表转换为MultiIndex
MultiIndex.from_arrays()
:将数组列表转换为MultiIndex
MultiIndex.from_product()
:从多个集合的笛卡尔乘积中创建MultiIndex
from_tuples()
方法可以将包含若干个元组的列表转换为MultiIndex
对象,其中元组的第一个元素作为外层索引,第二个元素作为内层索引,例如:
import pandas as pd
from pandas import MultiIndex
list_tuples = [('A', 'A1'), ('A', 'A2'), ('B', 'B1'), ('B', 'B2'), ('B', 'B3')]
multi_index = MultiIndex.from_tuples(tuples=list_tuples,
names=['外层索引', '内层索引'])
value = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
df_indexs = pd.DataFrame(data=value,index=multi_index)
print(df_indexs)
输出为:
0 1 2
外层索引 内层索引
A A1 1 2 3
A2 4 5 6
B B1 7 8 9
B2 10 11 12
B3 13 14 15
from_arrays()
方法是将数组列表转换为MultiIndex
对象,其中嵌套的第一个列表将作为外层索引,嵌套的第二个列表将作为内层索引。例如:
import pandas as pd
from pandas import MultiIndex
multi_array = MultiIndex.from_arrays(
arrays=[['A', 'A', 'B', 'B', 'B'], ['A1', 'A2', 'B1', 'B2', 'B3']])
value = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
df_indexs = pd.DataFrame(data=value, index=multi_array)
print(df_indexs)
输出:
0 1 2
A A1 1 2 3
A2 4 5 6
B B1 7 8 9
B2 10 11 12
B3 13 14 15
from_product()
方法表示从多个集合的笛卡尔乘积创建一个MultiIndex
对象。
什么是笛卡尔乘积? 笛卡尔积的符号化为: A×B={(x,y)|x∈A∧y∈B} 例如,A={a,b}, B={0,1,2},则 A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)} B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}
例如:
import numpy as np
import pandas as pd
from pandas import MultiIndex
numbers = [0, 1, 2]
colors = ['green', 'purple']
multi_product = MultiIndex.from_product(iterables=[numbers, colors],
names=['number', 'color'])
value = np.array([[7, 5], [6, 6], [3, 1], [5, 5], [4, 5], [5, 3]])
df_product = pd.DataFrame(data=value, index=multi_product)
print(df_product)
输出为:
0 1
number color
0 green 7 5
purple 6 6
1 green 3 1
purple 5 5
2 green 4 5
purple 5 3
5.3 层次化索引操作
任务一:录入下面层次化对象
代码:
import pandas as pd
ser_obj = pd.Series([78, 65, 44, 98, 66, 100, 97, 68],
index=[['机械', '机械', '机械', '信息', '信息', '工程', '工程', '工程'],
['张三', '李四', '王二', '宋天', '汪全', '寒月', '天使', '葛藤']])
输出:
机械 张三 78
李四 65
王二 44
信息 宋天 98
汪全 66
工程 寒月 100
天使 97
葛藤 68
dtype: int64
任务二:筛选外层索引为机械的数据
代码:
print(ser_obj['机械'])
输出:
张三 78
李四 65
王二 44
dtype: int64
任务三:筛选内层索引为李四的数据
代码:
print(ser_obj[:, '李四'])
输出:
机械 65
dtype: int64
任务四:交换分层顺序
代码:
print(ser_obj.swaplevel())
输出:
张三 机械 78
李四 机械 65
王二 机械 44
宋天 信息 98
汪全 信息 66
寒月 工程 100
天使 工程 97
葛藤 工程 68
dtype: int64
任务五:索引排序
sort_index()
语法sort_index(axis=0,level=None,ascending=True,inplace=False,kind='quicksort',na_position='last',sort_remaining=True,by=None)
by
:表示按指定的值排序ascending
:布尔值,表示是否升序排列,默认为True
代码:
print(ser_obj.sort_index())
输出:
信息 宋天 98
汪全 66
工程 天使 97
寒月 100
葛藤 68
机械 张三 78
李四 65
王二 44
dtype: int64
层次化索引中先对外层索引进行排序再对每一个外层索引的内层索引进行排序。如果需要对值进行排序可以使用sort_values()
函数。
任务六:录入下面的层次化对象并对num
列进行降序排序
代码:
import pandas as pd
dat_obj = pd.DataFrame(
{
"model": [
'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
'DRIVE'
],
"num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
},
index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
[1, 2, 4, 3, 5, 1, 5, 8, 1]])
print(dat_obj.sort_values(by='num', ascending=False))
输出:
model num
B 3 SSD 354
C 1 USB 231
A 2 GPU 152
4 FLASH 113
1 CPU 80
C 5 TYPE-C 35
8 MIC-USB 12
1 DRIVE 7
B 5 HDD 1
6. 数据的读写
6.1 读写文本文件
6.1.1 写入文本文件函数to_csv()
函数语法:
详细参数请查看官方文档:DataFrame.to_csv()
to_csv(path_or_buf=None,sep=',',na_rep='',float_format=None,columns=None,header=True,index=True,index_label=None,mode='w',……)
path_or_buf
:文件路径index
:默认为True
,若设为False
,则将不会显示索引sep
:分隔符,默认用","隔开
代码:
import pandas as pd
data_csv = pd.DataFrame(
{
"model": [
'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
'DRIVE'
],
"num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
},
index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
[1, 2, 4, 3, 5, 1, 5, 8, 1]])
data_csv.to_csv('./test.csv', index=True)
这种方法同样可以输出扩展名为
txt
的文件。
输出:
在本目录会生成一个text.csv
的文件,文件内容为:
,,model,num
A,1,CPU,80
A,2,GPU,152
A,4,FLASH,113
B,3,SSD,354
B,5,HDD,1
C,1,USB,231
C,5,TYPE-C,35
C,8,MIC-USB,12
C,1,DRIVE,7
6.1.2 读取文本文件函数read_csv()
函数语法:
详细参数请查看官方文档:Pandas.read_csv()
Pandas.read_csv(filepath_or_buffer,sep=',',delimiter=None,header='infer',names=None,index_col=None,usecols=None,prefix=None,……)
sep
:指定使用的分隔符,默认用","分隔header
:指定行数用来作为列名names
:用于结果的列名列表,如果文件不包含标题行,则应该将参数设置为None
读取Text文件函数
read_table()
与read_csv()
相似,只不过read_table()
函数默认使用"\t"为分隔符。
代码:
读取上文中生成的test.csv
文件
import pandas as pd
data = pd.read_csv('./test.csv')
print(data)
输出:
Unnamed: 0 Unnamed: 1 model num
0 A 1 CPU 80
1 A 2 GPU 152
2 A 4 FLASH 113
3 B 3 SSD 354
4 B 5 HDD 1
5 C 1 USB 231
6 C 5 TYPE-C 35
7 C 8 MIC-USB 12
8 C 1 DRIVE 7
可以通过del data['Unnamed: 0']
来删除该列。
6.2 读写EXCEL
文件
excel文件是常见的存储数据文件,它里面均是以二维表格的形式显示的,可以对数据进行统计分析等操作,常见扩展名为.xls
和.xlsx
两种格式,对于excel文件的读写常用的两个方法为to_excel()
和read_excel()
两种方法。
6.2.2 写入excel文件to_excel()
方法
函数语法:
详细参数请查看官方文档:DataFrame.to_excel()
DataFrame.to_excel(excel_writer,sheet_name='Sheet1',na_rep='',float_format=None,columns=None,header=True,index=True,……)
excel_writer
:表示读取的文件路径sheet_name
:表示工作表名称,默认为Sheet1
na_rep
:表示缺失数据index
:表示是否写行索引,默认为True
代码:
读取上文中生成的test.csv
文件
import pandas as pd
data_excel = pd.DataFrame(
{
"model": [
'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
'DRIVE'
],
"num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
},
index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
[1, 2, 4, 3, 5, 1, 5, 8, 1]])
data_excel.to_excel('./test.xlsx', 'Testexcel')
输出:
将在根目录输出文件名为test.xlsx
的表格,表格内容如图。
6.2.2 读取excel文件read_excel()
方法
注意:有关
Excel
的操作在Python 3.8
下可能会报错,建议使用Python 3.7
函数语法:
详细参数请查看官方文档:Pandas.read_excel()
Pandas.read_excel(io,sheet_name=0,header=0,name=None,index_col=None,**kwds)
io
:表示路径对象sheet_name
:指定要读取的工作表,默认为0header
:用于解析DataFrame的列标签,默认为0,即取第一列为列标题index_col
:用于解析DataFrame的行标签,默认为None
,如果表格中第一列为索引则将该属性设置为0names
:要使用的列名称
代码:
读取上文中生成的test.xlsx
文件,由于excel中合并的单元格会产生缺失值,使用ffill()
方法进行向下填充。
import pandas as pd
data = pd.read_excel('./test.xlsx').ffill()
print(data)
输出:
Unnamed: 0 Unnamed: 1 model num
0 A 1 CPU 80
1 A 2 GPU 152
2 A 4 FLASH 113
3 B 3 SSD 354
4 B 5 HDD 1
5 C 1 USB 231
6 C 5 TYPE-C 35
7 C 8 MIC-USB 12
8 C 1 DRIVE 7
6.3 读写HTML
文件
6.3.1 读取HTML表格方法read_html()
方法
函数语法:
详细参数请查看官方文档:pandas.read_html()
Pandas.read_html(io,match='.+',flavor=None,header=None,index_col=None,skiprows=None,attrs=None)
io
:表示路径对象header
:表示指定列标题所在的行index_col
:表示指定行标题对应的列attrs
:默认为None,用于表示表格的属性值
代码:
将使用read_html()
方法读取http://gaokao.xdf.cn/201805/10781393.html的表格:
import requests
import pandas as pd
html_data = requests.get('http://gaokao.xdf.cn/201805/10781393.html')
html_read = pd.read_html(html_data.content, encoding='utf-8')
print(html_read[0])
输出:
0 1 2 3
0 排名 学校名称 省市 总分
1 1 清华大学 北京 95.3
2 2 北京大学 北京 78.6
3 3 浙江大学 浙江 73.9
4 4 上海交通大学 上海 73.1
.. .. ... .. ...
95 94 中国政法大学 北京 37.6
96 96 大连医科大学 辽宁 37.5
97 97 中国石油大学(北京) 北京 37.3
98 98 西北大学 陕西 37.2
99 98 中国传媒大学 北京 37.2
[100 rows x 4 columns]
6.3.2 写入HTML表格方法to_html()
方法
函数语法:
详细参数请查看官方文档:DataFrame.to_html()
DataFrame.to_html(buf,index,header)
buf
:输出路径index
:行索引,默认为True
header
:列索引,默认为True
代码:
将上文读取到的表格的前十名写入到test.html
中,不保留行列索引:
html_read[0][:11].to_html('./test.html', index=False, header=False)
输出:
6.4 读写sql
文件
Padnas支持Mysql、Oracle、SQLite等主流数据库的读写操作,为了高效读取数据库中的数据,需要引入SQLAlchemy软件,引入之后Pandas的io.sql
模块将读写数据库,其中提供的常用函数如下表所示:
函数名称 | 说明 |
---|---|
read_sql_table() |
将读取的整张数据表中的数据转化成DataFrame对象 |
read_sql_query() |
将sql语句读取的结果转换成DataFrame对象 |
read_sql() |
上述两个函数的结合,既可以读数据表也可读SQL语句 |
to_sql() |
将数据写入到SQL数据库中 |
本文将使用mysql数据库,Python需要使用:
pip install mysql-connector-python
如果使用的是Conda则需要使用:
conda install mysql-connector-python
安装模块。
6.4.1 写入数据库函数to_sql()
函数语法:
详细参数请查看官方文档:DataFrame.to_sql() Series.to_sql()
to_sql(name,con,schema=None,if_exists='fail',index=True,index_label=None,chunksize=None,dtype=None)
name
:表示数据库表的名称con
:接收数据库连接信息if_exists
:可以取值为fail
,replace
,append
等,默认为fail
在对数据库进行写入前需要首先创建数据库,使用mysql终端输入:
create database test;
代码:
创建一个DataFrame
对象并将其写入test
数据库中的students
表。
from sqlalchemy import create_engine
import pandas as pd
df = pd.DataFrame({
"班级": ["一年级", "二年级", "三年级", "四年级"],
"男生人数": [25, 23, 27, 30],
"女生人数": [19, 17, 20, 20]
})
engine = create_engine("mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
df.to_sql('students',engine)
输出:
通过在Mysql数据库中输入:
use test; /*使用test数据库*/
show tables; /*显示数据库中的数据表*/
select *from students; /*输出students数据表*/
至此,表格已经创建成功了。
6.4.1 读取数据表函数read_sql()
函数语法:
详细参数请查看官方文档:pandas.read_sql()
pandas.read_sql(sql,con,index_col=None,coerce_float=True,params=None,parse_dates=None,columns=None,chunksize=None)
sql
:表示被执行的SQL语句con
:接收数据库连接,表示数据库的连接信息columns
:从SQL表中选择列名列表
注意:通过
create_engine()
函数创建连接时,需要指定格式如下:'数据库类型+数据库驱动名称//用户名:密码@机器地址:端口号/数据库名'
代码:
读取上文中test/students
数据表中的内容并写入名称为data_sql
的DataFrame
对象中。
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine(
"mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
sql = "select *from students"
data_sql = pd.read_sql(sql, engine)
print(data_sql)
输出:
index 班级 男生人数 女生人数
0 0 一年级 25 19
1 1 二年级 23 17
2 2 三年级 27 20
3 3 四年级 30 20