Pandas 是一个以 NumPy 为基础,专门为解决数据分析任务而创建的库,该库中不仅提供了一些标准的数据模型,而且提供了高效操作大量数据的数据结构,被广泛地运用到诸如金融、统计等一些领域中。
数据结构
Pandas 中提供了两种比较重要的数据结构,分别是 Series 和 DataFrame,其中 Series 是一维数据结构。
导入语法:import pandas as pd
Series
Series 是类似于一维数组的数据结构,主要由一组数据和与之相关的索引两部分组成,其中数据可以是任意类型的,比如整数、字符串、浮点数、Python 对象等。
创建 Series 对象语法:
Series(data = None ,index = None ,dtype = None ,name = None ,copy = False ,fastpath = False)
参数含义:
- data:表示数据,他的值可以是 ndarray 对象、列表、字典、标量等。
- index:表示索引,它的值必须是散列的,且与数据的长度相同。
- dtype:表示数据的类型,它的值可以是 numpy.dtype 。
# 创建 Series 对象
ser = pd.Series(data = ['Python','C','Java','Javascript','PHP','R'])
# 结果:0 Python
1 C
2 Java
3 Javascript
4 PHP
5 R
# 创建 Series 对象
ser = pd.Series(data = ['Python','C','Java','Javascript','PHP','R'] ,index = ['a','b','c','d','e','f'])
# 结果:a Python
b C
c Java
d Javascript
e PHP
f R
Series 对象获取索引和数据:
ser.index:获取 Series 的索引数据ser.values:获取 Series 的数据
# 创建 Series 对象
ser = pd.Series(data = ['Python','C','Java','Javascript','PHP','R'])
ser.index
# 结果:Index(['a','b','c','d','e','f'],dtype = 'object')
ser.values
# 结果:array(['Python', 'C', 'Java', 'Javascript', 'PHP', 'R'], dtype=object)
DataFrame
DataFrame 是一个类似于二维数组或表格的数据结构,它通过行列的形式组织数据,每列数据可以是不同的数据类型。
DataFrame 对象的创建语法:
DataFrame(data = None .index = None ,column = None ,dtype = None ,copy = None)
参数说明:
- data:表示数据,该参数可以接收 ndarray 对象、列表、字典或其他 DataFrame 类的对象。
- index:表示行索引
- columns:表示列索引
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr)
# 结果: 0 1 2 3 4
1 1 2 3 4 5
2 6 7 8 9 10
3 11 12 13 14 15
4 16 17 18 19 20
5 21 22 23 24 25
6 26 27 28 29 30
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
# 结果: No1 No2 No3 No4 No5
1 1 2 3 4 5
2 6 7 8 9 10
3 11 12 13 14 15
4 16 17 18 19 20
5 21 22 23 24 25
6 26 27 28 29 30
为了便于用户从整体连接数据的摘要信息,可以使用 info() 函数来查看。
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.info()
# 结果:
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 6 entries, 0 to 5
# Data columns (total 5 columns):
# Column Non-Null Count Dtype
# --- ------ -------------- -----
# 0 No1 6 non-null int64
# 1 No2 6 non-null int64
# 2 No3 6 non-null int64
# 3 No4 6 non-null int64
# 4 No5 6 non-null int64
# dtypes: int64(5)
memory usage: 372.0 bytes
查看所有元素的值:df.values
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.values
# 结果:
# array([[ 1, 2, 3, 4, 5],
# [ 6, 7, 8, 9, 10],
# [11, 12, 13, 14, 15],
# [16, 17, 18, 19, 20],
# [21, 22, 23, 24, 25],
# [26, 27, 28, 29, 30]])
查看所有元素的唯一值数量
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.nunique()
# 结果:
# No1 6
# No2 6
# No3 6
# No4 6
# No5 6
查看所有元素的类型
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.dtypes
# 结果:
# No1 int64
# No2 int64
# No3 int64
# No4 int64
# No5 int64
查看所有行名
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.index
# 结果:RangeIndex(start=0, stop=6, step=1)
重命名行名
pdObj.index = ['A','B','C']
查看所有列名
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.columns
# 结果:Index(['No1', 'No2', 'No3', 'No4', 'No5'], dtype='object')
重命名列名
pdObj.columns = ['a','b','c']
行列转置
# 创建二维数组
arr = np.arange(1,31).reshape((6,5))
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = arr ,columns = ['No1','No2','No3','No4','No5'])
pdObj.T
# 结果:
# 0 1 2 3 4 5
# No1 1 6 11 16 21 26
# No2 2 7 12 17 22 27
# No3 3 8 13 18 23 28
# No4 4 9 14 19 24 29
# No5 5 10 15 20 25 30
索引与切片
在 Pandas 中,无论是位置索引还是标签索引,它们都属于是 Index 类的对象,也就是索引对象。Index 类是一个基类,他派生了很多子类,每个子类代表不同形式的索引。
| 类 | 说明 | 示例 |
| RangeIndex | 位置索引(默认) | 0,1,2,3,……N |
| Int64Index | 整数索引 | 1,-5,8,10,-9 |
| Float64Index | 浮点数索引 | -1.0 ,-5.5 ,10.2 ,9.8 ,6.3 |
| DatetimeIndex | 时间戳索引 | 2022-11-22 17:00:00 ,2022-11-28 17:00:00 ,2022-12-25 17:00:00 |
| PeriodIndex | 时间间隔索引 | 2022-11-22 00:00:00 ,2022-11-22 01:00:00 ,2022-11-22 02:00:00 |
| MultiIndex | 分层索引 | a a ,a b ,a c ,b d ,b e |
索引对象主要有两种特性:
- 不可变性:
索引对象一旦创建是不可以直接修改的,即索引的值是固定不变的,这样做能够维护从索引到数据的唯一映射关系,保证 Series 或 DataFrame 中的数据的安全。
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = range(5) ,columns = ['a','b','c','d','e'])
pdObj.index
# 结果:['a','b','c','d','e']
pdObj.index[2] = 'f'
# 结果:TypeError......
- 可重复性:
索引对象的值是可以重复的。
# 创建 DataFrame 对象
pdObj= pd.DataFrame(data = range(5) ,columns = ['a','a','c','d','e'])
pdObj.index
# 结果:['a','a','c','d','e']
# 判断索引值是否唯一、不重复的
pdObj.is_unique
# 结果:False
重置索引
重置索引是指重新为对象设定索引,以构建一个符合新索引的对象。
Pandas 中通过 reindex() 方法实现重置索引的功能,reindex() 方法会对 Series 或 DataFrame 类对象的原索引和新索引进行匹配,如果新索引与原索引的值相同,则新索引对应的数据会被设置为原数据;反之,新索引对应的空缺位置会被填充为 NaN 或指定的其他值。
语法:reindex(labels = None ,index = None ,columns = None ,axis = None ,method = None ,copy = None ,level = None ,fill_value = nan ,limit = None ,tolerance = None)
参数说明:
- index:表示新的行索引
- columns:表示新的列索引
- method:表示空缺位置的填充方式(包括
None(默认值)、ffill或pad、bfill或backfill、nearset等值)- None 代表不填充不填充空缺位置;
- ffill 或 pad 代表前向填充空缺位置;
- bfill 或 backfill 代表后向填充时的最大填充量。
- copy:是否返回新的对象(默认值为 True)
- fill_value:表示空缺位置被填充的值(默认为 NaN)
- limit:表示前向或后向填充时的最大填充量。
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = {'no1':[1.0,2.0,3.0],'no2':[4.0,5.0,6.0]} ,index = ['a','b','c'])
pdObj
# 结果:
# no1 no2
#a 1.0 4.0
#b 2.0 5.0
#c 3.0 6.0
# 重置索引
newDF = pdObj.reindex(index = ['a','c','e'])
# 结果:
# no1 no2
#a 1.0 4.0
#c 3.0 6.0
#e NaN NaN
注意:e 行的数据全部显示为 NaN,这是因为 dfObj 对象中没有行索引 e,当对 dfObj 对象重置索引时,该索引对应的数据被填充为 NaN。
如果不想填充为 NaN,可以通过 fill_value 参数来指定值。
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = {'no1':[1.0,2.0,3.0],'no2':[4.0,5.0,6.0]} ,index = ['a','b','c'])
pdObj
# 结果:
# no1 no2
#a 1.0 4.0
#b 2.0 5.0
#c 3.0 6.0
# 重置索引
newDF = pdObj.reindex(index = ['a','c','e'] ,fill_value = 9)
# 结果:
# no1 no2
#a 1.0 4.0
#c 3.0 6.0
#e 9.0 9.0
如果希望使用不同值填充空缺位置,可以使用 method 参数来填充指定填充方式。
# 创建 DataFrame 对象
pdObj = pd.DataFrame(data = {'no1':[1.0,2.0,3.0],'no2':[4.0,5.0,6.0]} ,index = ['a','b','c'])
pdObj
# 结果:
# no1 no2
#a 1.0 4.0
#b 2.0 5.0
#c 3.0 6.0
# 重置索引
newDF = pdObj.reindex(index = ['a','c','e'] ,method = 'ffill')
# 结果:
# no1 no2
#a 1.0 4.0
#c 3.0 6.0
#e 3.0 6.0
通过索引和切片获取数据
Pandas 中通过索引或切片来获取 Series 类和 DataFrame 类对象的数据。
Series 的索引和切片操作
Series 类对象与 NumPy 一维数组的索引用法相似,不同的是,Series 类对象的索引既可以是位置索引,也可以是标签索引。
ser = pd.Series([10,20,30,40,50] ,index = ['one','two','three','four','five'])
# 通过位置索引
ser[2]
# 结果:30
# 通过标签索引
ser['one']
# 结果:10
如果想要获取 Series 类对象的多个数据,则可以通过包含多个位置索引或标签索引的列表进行获取。
ser = pd.Series([10,20,30,40,50] ,index = ['one','two','three','four','five'])
# 通过位置索引
ser[[0,2,3]]
# 结果:
# one 10
# two 20
# three 40
# 通过标签索引
ser['one','two','three']
# 结果:
# one 10
# two 20
# three 30
布尔索引也同样适用于 Pandas,具体用法与一维数组的布尔索引用法相同。
ser = pd.Series([10,20,30,40,50] ,index = ['one','two','three','four','five'])
ser > 20
# 结果:
# one False
# two False
# three True
# four True
# five True
ser[ser > 20]
# 结果:
# three 30
# four 40
# five 50
切片也可以获取 Series 类对象中的部分数据。
ser = pd.Series([10,20,30,40,50] ,index = ['one','two','three','four','five'])
ser[1:3]
# 结果:
# two 20
# three 30
ser['one':'four']
# 结果:
# two 20
# three 30
# four 40
DataFrame 的索引和切片操作
DataFrame 类对象与 NumPy 二维数组的索引用法相似,它里面每一列的数据都是一个 Series 类的对象,可以通过列索引进行获取。
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
pdObj['col_2']
# 结果:
# row_1 1
# row_2 3
# row_3 8
如果想要从 DataFrame 中获取多列数据,那么可以将多个索引存放到列表中。
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
pdObj[['col_2','col_4']]
# 结果:
# col_2 col_4
# row_1 1 3
# row_2 3 6
# row_3 8 10
如果想要从 DataFrame 对象中获取多行数据,那么可以通过切片来完成。
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
pdObj[1:3]
# 结果:
# col_1 col_2 col_3 col_4
# row_2 4 3 5 6
# row_3 7 8 9 10
还可以通过切片获取部分行和部分列德数据。
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
pdObj[1:3][['col_1','col_3']]
# 结果:
# col_1 col_3
# row_2 4 5
# row_3 7 9
通过 loc 和 iloc 属性获取数据
- loc:基于标签索引的索引器
- iloc:基于位置索引的索引器
通过 loc 属性获取数据
语法:
Series对象.loc[参数]
DataFrame对象.loc[参数1 , 参数2 ...]
参数可以接收多种形式的对象,常见的情况如下:
- 单个标签索引
- 标签索引构成的列表或数组,如:[‘a’,’b’,’c’]、[‘col1′,’col2’] 等。
- 基于标签索引的切片,如:’a’:’c’、’two’:’four’ 等。
- 布尔类型的列表、数组或 Series,比如:[True,Falsse,True] 等。
以 Series 对象为例:
ser = pd.Series([10,20,30,40,50] ,index = ['row1','row2','row3','row4','row5'])
# 根据单个标签索引获取单个数据
ser.loc['row2']
# 结果:20
ser = pd.Series([10,20,30,40,50] ,index = ['row1','row2','row3','row4','row5'])
# 根据标签索引构成的列表获取多个数据
ser.loc[['row2','row4']]
# 结果:
# row2 20
# row4 40
ser = pd.Series([10,20,30,40,50] ,index = ['row1','row2','row3','row4','row5'])
# 根据基于标签索引的切片获取多个连续数据
ser.loc['row2':'row5']
# 结果:
# row2 20
# row3 30
# row4 40
ser = pd.Series([10,20,30,40,50] ,index = ['row1','row2','row3','row4','row5'])
# 根据布尔类型的 Series 对象获取符合条件的数据
ser.loc[ser < 30]
# 结果:
# row1 10
# row2 20
以 DataFrame 对象为例:
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据单个标签索引获取一行数据
pdObj.loc['row_1']
# 结果:
# col_1 0
# col_2 1
# col_3 2
# col_4 3
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据标签索引偶成的列表获取多行数据
pdObj.loc[['row_1','row_3']]
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_3 7 8 9 10
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据基于标签索引的切片获取连续多行数据
pdObj.loc['row_1':'row_3']
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据布尔类型的列表获取符合条件的多行数据
pdObj.loc[[True,False,True]]
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_3 7 8 9 10
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据两个标签索引获取单个数据
pdObj.loc['row_3','col_2']
# 结果:9
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据切片和列表获取多列数据
pdObj.loc['row_1':'row_3',['col_1','col_3']]
# 结果:
# col_1 col_3
# row_1 0 2
# row_2 7 9
# row_3 7 9
通过 iloc 属性获取数据
语法格式:
Series.iloc[ 参数 ]
DataFrame.iloc[ 参数1 , 参数2 ]
参数可以接收多种形式的对象,常见的情况主要有一下几种:
- 单个位置索引
- 位置索引构成的列表或数组,如 [0,1,2] 等
- 基于位置索引的切片,如 0:2、2:5 等
- 布尔类型的列表、数组或 Series,如 [True,False,True]等,长度必须与被索引对象中一行或一列数据的个数相同
以 DataFrame 对象为例:
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据单个位置索引获取一行数据
pdObj.iloc[0]
# 结果:
# col_1 0
# col_1 1
# col_1 2
# col_1 3
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据位置索引构成的列表获取多行数据
pdObj.iloc[[0,2]]
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_3 7 8 9 10
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据基于位置索引的切片获取连续多行数据
pdObj.iloc[0:2]
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据布尔类型的列表获取符合条件的多行数据
pdObj.iloc[[True,False,True]]
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_3 7 8 9 10
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据两个位置索引获取单个数据
pdObj.iloc[2,2]
# 结果:10
arr = np.arange(12).reshape(3,4)
# 创建 DataFrame 对象
pdObj = pd.DataFrame(arr ,index = ['row1'.'row_2','row_3','row_4'] ,columns = ['col_1','col_2','col_3','col_4'])
pdObj
# 结果:
# col_1 col_2 col_3 col_4
# row_1 0 1 2 3
# row_2 4 3 5 6
# row_3 7 8 9 10
# row_4 11 12 13 14
# 根据切片和列表获取多列数据
pdObj.iloc[0:3,[0,2]]
# 结果:
# col_1 col_3
# row_1 0 2
# row_2 4 5
# row_3 7 9
读写数据
在数据分析中,数据通常会被保存在文件或数据库中,为例方便用户操作数据,Pandas 提供了一系列读物数据或写入数据的方法。
读写 CSV 和 TXT 文件的数据
Pandas 中提供了 read_csv() 函数用于从 CSV 或 TXT 文件中读取数据,Pandas 中的 Series 和 DaataFrame 类中还提供了 to_csv() 方法用于向 CSV 或 TXT 文件中写入数据。
to_csv(pathOrBuf = None ,sep = ',' ,na_rep = '' ,float_format = None ,columns = None ,header = True ,index = True ,index_label = None ,mode = 'w' ,encoding = None ,compression = 'infer' ,quoting = None ,quotechar = '"' ,line_terminator = None ,chunkisze = None ,date_format = None ,doublequote = True ,escapechar = None ,decimal = '.' ,errors = 'strict' ,storage_options = None)- 常用参数的含义:
- pathOrBuf:表示文件的路径,文件路径可以是绝对路径或相对路径,如果参数只是该文件的名称则会保存在当前目录下。
- na_rep:表示缺失数据的表示方式,默认值是空字符串
- sep:表示文件使用的字段分隔符(默认值是 , ,长度必须为1)
- columns:表示向文件中写入那几列数据
- header:表示文件是否显示的列标题
- index:表示是否向文件中写入行索引(默认值为 True)
- 常用参数的含义:
df = pd.DataFrame({'编号':['CNN001','CNN002','CNN003','CNN004','CNN005','CNN006','CNN007','CNN008','CNN009','CNN0010'],
'姓名':['小明','小红','小兰','小字','小黑','小白','小黄','小芳','小刚','小丽'],
'性别':['男','女','女','男','男','男','女','女','男','女'],
'部门':['行政','人力资源','销售','研发','财务','技术','市场','研发','财务','市场'],
'职务':['员工','主管','员工','主管','员工','员工','主管','员工','员工','主管']})
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
df.to_csv(r'info.csv' ,index = False ,encoding = 'gbk')
read_csv(filePathOrBuffer ,sep = NoDefault.no_default ,delimiter = None ,header = 'infer' ,names = NoDefault.no_default ,index_col = None ,encoding = None ,... ,storage_options = None)- 常用参数的含义:
- filePathOrBuffer:表示文件的路径
- sep:表示文件使用的分隔符。如果没有指定分隔符,则会尝试使用逗号进行分割
- header:指定文件中哪一行作为列索引以及数据的开头,默认会根据 names 参数推断列索引,如果没有给 names 参数传值,则 header 的值为 0,说明列索引是根据文件的第一行内容推断出来的。
- names:表示要使用的列名称的列表。如果文件包含标题行,则应该显示传递 header = 0 以覆盖列名称
- encoding:表示读取文件时使用的编码格式。
- 常用参数的含义:
df = pd.read_csv(r'info.csv' ,encoding='gbk')
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
除了使用 read_csv() 函数读取 TXT 文件外,还可以使用 read_table() 函数读取 TXT 文件,两者的区别在于默认使用的分隔符不同,前者使用的分隔符是逗号,后者使用的分隔符是制表符。
df = pd.read_table(r'info.csv' ,encoding='gbk')
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
扩展:
Pandas 中额外提供了 head() 和 tail() 方法,其中 head() 方法用于预览前 N 行数据(默认是前 5 行数据);tail() 方法用于预览后 N 行数据(默认是后 5 行数据)。
df = pd.read_table(r'info.csv' ,encoding='gbk')
df.head()
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
df = pd.read_table(r'info.csv' ,encoding='gbk')
df.head(3)
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
df = pd.read_table(r'info.csv' ,encoding='gbk')
df.tail()
# 结果:
# 编号 姓名 性别 部门 职务
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
df = pd.read_table(r'info.csv' ,encoding='gbk')
df.tail(2)
# 结果:
# 编号 姓名 性别 部门 职务
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
读写 Excel 文件的数据
Excel 文件时数据分析工作中比较常用的存储数据的文件,它里面可以添加若干个工作表(Sheet),每个工作表都是以表格的形式显示数据,并支持对数据进行统计、分析等操作。
Pandas 中提供了读写 Excel 文件数据的功能,分别是 to_excel() 和 read_excel() 函数,其中 to_excel() 方法用于向 Excel 文件中写入数据,read_excel() 函数用于从 Excel 文件中读取数据。
to_excel(excelWriter ,sheetName = 'Sheet1' ,na_rep = '' ,float_format = None ,columns = None ,header = True ,index = True ,index_label = None ,startrow = 0 ,startcol = 0 ,engine = None ,merge_cells = True ,encoding = None ,inf_rep = 'inf' ,verbose = True ,freeze_panes = None ,storage_options = None)- 常用参数的含义:
- excelWriter:表示写入文件的路径
- sheet_name:表示工作表的名称,可以接收字符串(默认值为 Sheet1)
- na_rep:表示缺失数据的表现形式
- index:表示是否向文件中写入行索引(默认值为 True)
- 常用参数的含义:
df = pd.DataFrame({'编号':['CNN001','CNN002','CNN003','CNN004','CNN005','CNN006','CNN007','CNN008','CNN009','CNN0010'],
'姓名':['小明','小红','小兰','小字','小黑','小白','小黄','小芳','小刚','小丽'],
'性别':['男','女','女','男','男','男','女','女','男','女'],
'部门':['行政','人力资源','销售','研发','财务','技术','市场','研发','财务','市场'],
'职务':['员工','主管','员工','主管','员工','员工','主管','员工','员工','主管']})
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
df.to_excel(r'info.csv')
read_excel(io ,sheet_name = 0 ,header = 0 ,names = None ,index_col = None ,usecols = None ,squeeze = None ,dtype = None ,engine = None ,conmverters = None ,true_values = None ,false_values = None ,... ,storage_options = None)- 常用参数的含义:
- io:表示文件的路径
- sheet_name:指定要读取工作表的名称(默认值为0,说明读取第一个工作表)
- header:指定文件中的哪一行数据作为 DataFrame 类对象的列索引
- names:表示要使用的列名称
- index_col:指定文件中的那一列数据作为 DataFrame 的行索引,该参数支持整数、整数列表和 None(默认值)三种类型的取值
- 整数:表示列索引,则会将该索引对应的一列数据作为行索引
- 证书列表:表示将这些整数作为索引获取多列数据,并将这些数据组合成 MultiIndex 类对象后作为行索引
- None:自动生成一组位置索引
- usecols:指定读取哪几列数据(默认值为 None,说明会读取所有列的数据),该参数可以接收一个列表,列表中的元素分别对应列的编号(编号从 0 开始)
- 常用参数的含义:
df = pd.read_excel(r'info.xlsx')
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
df = pd.read_excel(r'info.xlsx' ,usecols = [1,2,3,4,5,6])
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
df = pd.read_excel(r'info.xlsx',sheet_name = '工作表2',header = 1)
# 结果:
# 编号 姓名 性别 部门 职务
# 0 CNN001 小明 男 行政 员工
# 1 CNN002 小红 女 人力资源 主管
# 2 CNN003 小兰 女 销售 员工
# 3 CNN004 小字 男 研发 主管
# 4 CNN005 小黑 男 财务 员工
# 5 CNN006 小白 男 技术 员工
# 6 CNN007 小黄 女 市场 主管
# 7 CNN008 小芳 女 研发 员工
# 8 CNN009 小刚 男 财务 员工
# 9 CNN0010 小丽 女 市场 主管
读取网页表格数据
在浏览网页时,有些数据会在 HTML 网页中以表格的形式进行展示,对于这部分数据,可以使用 Pandas 中的 read_html() 函数进行读取,读取成功后会返回一个列表,该列表中包含对应网页表格的 DataFrame 类的对象。
read_html(io ,match = '.+' ,flavor = None ,index_col = None ,skiprows = None ,attrs = None ,parse_datas = False ,thousands = ',' ,encoding = None ,decimal = '.' ,converters = None ,na_values = None ,keep_default_na = True ,displayed_only = True)- 常用参数的含义:
- io:表示 HTML 网页的字符串、路径对象或类似文件的对象。若参数 io 的值是字符串,则字符串的内容可以是 URL ,也可以是 HTML 代码
- match:表示返回包含正则表达式或字符串匹配的文本的一组表格(默认值为 .+,说明匹配任何非空字符串)
- header:用于指定列标题所在的行
- index_col:用于指定行标题所在的列
- 常用参数的含义:
pd.read_html(io='https://www.tiobe.com/tiobe-index/')[3]
# 结果:
Year Winner
0 2025 C#
1 2024 Python
2 2023 C#
3 2022 C++
4 2021 Python
5 2020 Python
6 2019 C
7 2018 Python
8 2017 C
9 2016 Go
10 2015 Java
11 2014 JavaScript
12 2013 Transact-SQL
13 2012 Objective-C
14 2011 Objective-C
15 2010 Python
16 2009 Go
17 2008 C
18 2007 Python
19 2006 Ruby
20 2005 Java
21 2004 PHP
22 2003 C++
导入 Json 文件
Json 文件有结构化数据和非结构化数据,如果是非表单结构,读取无意义。常见的表达结构有:split、records、index、table、values。
pd.read_json('a.json' ,orient = 'records');
读写数据库
Pandas 中提供了一些用于读写 Mysql 数据库的函数或方。
| 函数 / 方法 | 说明 |
| read_sql_table() | 根据数据表的名称读取数据库的数据,并将读取的结果转换成一个 DataFrame 类的对象后返回 |
| read_sql_query() | 根据 SQL 语句读取数据库的数据,并将读取的结果转换成一个 DataFrame 类的对象后返回 |
| read_sql() | 上述两个函数的结合,可以根据数据表名称或 SQL 语句读取数据库的数据 |
| to_sql() | 将 Series 类或 DataFrame 类的对象写入到数据库中 |
to_sql(name ,con ,schema = None ,if_exists = 'fail' ,index = True ,index_label = None ,chunksize = None ,dtype = None)- 常用参数的含义:
- name:表示数据表的名称
- con:表示数据库的连接信息。该参数的值可以是 Engine 类或 Connection 类的对象。若希望创建一个 Engine 类的对象,则需要通过 create_engine() 函数实现,该函数需要接收一个符合格式要求的字符串,具体格式为
数据库类型 + 数据库驱动名称://用户名:密码@机器地址:端口号/数据库名。 - if_exists:表示当数据表存在时如何操作数据表,该参数可以取值为 fail、replace 或 append(默认值为 fail)
- fail:表示不执行写入操作
- replace:表示将元数据表删除后再重新创建
- append:表示在原数据表的基础上追加数据
- index:表示是否将 DataFrame 的行索引作为数据写入数据库(默认值为 True)
- index_label:表示是否引用索引名称。如果 index 设为 True,此参数为 None,表示使用默认名称;如果 index 为分层索引,则他的值必须是序列类型
- 常用参数的含义:
from pandas import DataFrame,Series
from sqlalchemy import crteate_engine
from sqlalchemy.types import *
df = DataFrame({"班级":['一年级','二年级','三年级','四年级','五年级','六年级'],
"男生人数":[25,23,24,10,32,22],
"女生人数":[19,23,14,25,20,15]})
# 创建数据库引擎
# mysql+pymysql 表示使用 Mysql 数据库的 mysqlconnector 驱动
# root:123456 表示 Mysql 的用户名和密码
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1/students')
df.to_sql('student',engine)
read_sql(sql ,con ,index_col = None ,coerce_float = True ,params = None , parse_dates = None ,columns = None ,chunksize = None)- sql:表示被执行的 SQL 语句
- con:接收数据库连接,表示数据库的连接信息
- index_col:表示将数据表中的列标题作为 DataFrame 类对象的行索引
- coerce_float:将非空字符串、非数字对象的值强制转换为浮点型数据
- params:传递给执行方法的参数列表,如 params = {‘name’:’value’}
from pandas import DataFrame,Series
from sqlalchemy import crteate_engine
from sqlalchemy.types import *
# 创建数据库引擎
# mysql+pymysql 表示使用 Mysql 数据库的 mysqlconnector 驱动
# root:123456 表示 Mysql 的用户名和密码
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1/students')
pd.read_sql('penson',engine)
from pandas import DataFrame,Series
from sqlalchemy import crteate_engine
from sqlalchemy.types import *
# 创建数据库引擎
# mysql+pymysql 表示使用 Mysql 数据库的 mysqlconnector 驱动
# root:123456 表示 Mysql 的用户名和密码
engine = create_engine('mysql+pymysql://root:123456@127.0.0.1/students')
pd.read_sql('select * from person where id > 3',engine)
数据排序
在数据分析中,数据排序时一种比较常见的操作。由于 Series 和 DataFrame 都是由索引和数据组成的,所以即可以按照索引进行排序,也可以按照值进行排序。
按索引排序
Pandas 中可以通过 sort_index() 方法实现按索引排序的功能,sort_index() 方法可以根据行索引或列索引的大小对 Series 类和 DataFrame 类的对象进行排序。
sort_index(axis = 0 ,level = None ,ascending = True ,inplace = False ,kind = 'quicksort' ,na_position = 'last' ,sort_remaining = True ,ignore_index = False ,key = None)- 常用的参数说明:
- axis:表示沿着哪个方向的轴排序,该参数的取值可以是 0 或 index(按行方向排序)、1 或 columns(按列方向排序)。
- ascending:表示是否升序排序(默认值为 True)
- king:表示排序算法,可以取值为 quicksort(快速排序算法)、mergesort(归并排序算法)、heapsort(堆排序算法)、stable(稳定排序算法)。
- 常用的参数说明:
df = pd.DataFrame(np.arange(9).reshape(3,3),index=[4,3,5])
# 生成结果:
# 0 1 2
# 4 0 1 2
# 3 3 4 5
# 5 6 7 8
df.sort_index()
# 生成结果:
# 0 1 2
# 3 3 4 5
# 4 0 1 2
# 5 6 7 8
df.sort_index(ascending = False)
# 生成结果:
# 0 1 2
# 5 6 7 8
# 4 0 1 2
# 3 3 4 5
按值排序
Pandas 中为 Series 类和 DataFrame 类的对象提供了按值排序的方法 sort_values()。
sort_values(by ,axis = 0 ,ascending = True ,inplace = False , kind = 'quicksort' ,na_position = 'last' ,ignore_index = False ,key = None)- 常用参数说明:
- by:表示排序的列
- na_position:表示 NaN 值的位置,他只有两种取值 last 和 first(默认值为 last)
- first:会将 NaN 值放在开头
- last:会将 NaN 值放在结尾
- 常用参数说明:
ser = pd.Series([4,np.nan,6,np.nan,-3,2])
# 结果:
# 0 4.0
# 1 NaN
# 2 6.0
# 3 NaN
# 4 -3.0
# 5 2.0
ser.sort_values()
# 结果:
# 4 -3.0
# 5 2.0
# 0 4.0
# 2 6.0
# 1 NaN
# 3 NaN
ser.sort_values(ascending = False)
# 结果:
# 2 6.0
# 0 4.0
# 5 2.0
# 4 -3.0
# 1 NaN
# 3 NaN
df = pd.DataFrame([[0.4 ,-0.1 ,-0.3 ,0.0],
[0.2 ,0.6 ,-0.1 ,-0.7],
[0.8 ,0.6 ,-0.5 ,0.1]])
# 结果:
# 0 1 2 3
# 0 0.4 -0.1 -0.3 0.0
# 1 0.2 0.6 -0.1 -0.7
# 2 0.8 0.6 -0.5 0.1
df.sort_values(by = 2)
# 结果:
# 0 1 2 3
# 2 0.8 0.6 -0.5 0.1
# 0 0.4 -0.1 -0.3 0.0
# 1 0.2 0.6 -0.1 -0.7
算术运算与数据对齐
在 Pandas 中,Series 类或 DataFrame 类的对象进行算术运算时,会先将对象中的索引相同的数据按位置对齐,对气候再进行相应的运算,没有对齐的位置会用 NaN 进行补齐。Series 是按行索引对齐的,DataFrame 是按行索引、列索引对齐的。
ser1 = pd.Series(np.arange(10,13),index=range(3))
# 生成结果:
# 0 10
# 1 11
# 2 12
ser2 = pd.Series(np.arange(20,25),index=range(5))
# 生成结果:
# 0 20
# 1 21
# 2 22
# 3 23
# 4 24
ser1 + ser2
# 结果:
# 0 30
# 1 31
# 2 32
# 3 NaN
# 4 NaN
# 执行加法运算并补齐缺失值
ser1.add(ser2 ,fill_value = 0)
# 结果:
# 0 30.0
# 1 31.0
# 2 32.0
# 3 23.0
# 4 24.0
统计计算与描述
Pandas 中提供了一些常用的数学和统计的函数或方法,使用这些方法可以轻松地对一行、一列或全部数据进行统计计算,此外也可以一次性的描述一组数据的所有统计指标。
统计计算
| 方法 | 说明 |
| sum() | 计算和 |
| mean() | 计算平均值 |
| median() | 计算中位数 |
| max() | 计算最大值 |
| min() | 计算最小值 |
| idxmax() | 计算最大索引值 |
| idxmin() | 计算最小索引值 |
| count() | 计算非 NaN 值的个数 |
| var() | 计算样本值的方差 |
| std() | 计算样本值的标准值 |
| skew() | 计算样本值的偏度(三阶矩) |
| kurt() | 计算样本值的峰度(四阶矩) |
| mode() | 计算众数 |
| cumsum | 计算样本值的累加和 |
| cummin()、cummax() | 计算样本值的累积最小值和累积最大值 |
| cumprod() | 计算样本值的累积乘 |
df = pd.DataFrame(np.arange(12).reshape(3,4),columns = ['a','b','c','d'])
# 生成结果:
# a b c d
# 0 0 1 2 3
# 1 4 5 6 7
# 2 8 9 10 11
df.sum()
# 结果:
# a 12
# b 15
# c 18
# d 21
df.max()
# 结果:
# a 8
# b 9
# c 10
# d 11
# 计算每行的最小值
df.min(axis = 1)
# 结果:
# 0 0
# 1 4
# 2 8
# 计算每行的均值
df.mean(axis = 1)
# 结果:
# 0 1.5
# 1 5.5
# 2 9.5
skipna:是否忽略空值(默认为 True)
# 设置一个空值
df['b'][2]=np.nan
# 结果:
# a b c d
# 0 0 1.0 2 3
# 1 4 5.0 6 7
# 2 8 NaN 10 11
# 计算每行的均值
df.mean(skipna=False)
# 结果:
# a 4.0
# b NaN
# c 6.0
# d 7.0
中位数是将一组数据从小到大进行排序后,位于中间位置的数值(如果为偶数,则取中间两数字的均值),自动忽略 NaN(可通过参数控制)。
DataFrame.median(axios = 0 ,skipna = True ,numeric_only = True)- axis:计算维度
- 0:按列计算每列的中位数(默认值)
- 1:按行计算每行的中位数
- skipna:是否忽略空值
- numeric_only:是否只计算数值型数列(int / float)
- axis:计算维度
Series.median(skipna = True ,numeric_only = True)
# 计算每行的中位数
df.median()
# 结果:
# a 4.0
# b 3.0
# c 6.0
# d 7.0
统计描述
如果希望一次性描述 Series 类或 DataFrame 类对象的多个统计指标,可以调用 describe() 方法实现。
describe(percentiles = None ,include = None ,exclude = None)- 常用参数含义:
- percentiles:表示结果包含的百分数,位于 [0,1] 之间。若不设置该参数,则默认为 [0.25 ,0.5 ,0.75] ,即展示四分之一位数、二分之一位数和四分之三位数。
- include:表示结果中包含数据类型的白名单(默认值为 None)
- exclude:表示结果中忽略数据类型的白名单(默认值为 None)
- 常用参数含义:
df = pd.DataFrame([[12 ,6 ,-11 ,19],
[-1 ,7 ,50 ,36],
[5 ,9 ,23 ,28]])
# 结果:
# 0 1 2 3
# 0 12 6 -11 19
# 1 -1 7 50 36
# 2 5 9 23 28
df.describe()
# 结果:
# 0 1 2 3
# count 3.000000 3.000000 3.000000 3.000000
# mean 5.333333 7.333333 20.666667 27.666667
# std 6.506407 1.527525 30.566867 8.504901
# min -1.000000 6.000000 -11.000000 19.000000
# 25% 2.000000 6.500000 6.000000 23.500000
# 50% 5.000000 7.000000 23.000000 28.000000
# 75% 8.500000 8.000000 36.500000 32.000000
# max 12.000000 9.000000 50.000000 36.000000
分层索引操作
分层索引可以理解为单层索引的延伸,即在一个轴上具有两层或两层以上的索引。
在 Pandas 中,分层索引其实就是一个 MultiIndex 类的对象。
| 方法 | 说明 |
| from_tuples() | 根据元组列表创建 MultiIndex 类的对象 |
| from_arrays() | 根据嵌套列表创建 MultiIndex 类的对象 |
| from_product() | 从多个集合的笛卡尔乘积中创建 MultiIndex 类的对象 |
参数:
- tuples:一个包含多个元素的列表
- names:一个包含两个字符串的列表(外层索引和内层索引)
from pandas import MultiIndex
# 创建一个包含多个元组的列表
list = [('A','A1'),('A','A2'),('B','B1'),('B','B2'),('B','B3')]
# 根据元组列表创建一个 MultiIndex 类的对象
multi = MultiIndex.from_tuples(tuples = list ,names = ['外层索引','内层索引'])
# 结果:
# MultiIndex([('A', 'A1'),
# ('A', 'A2'),
# ('B', 'B1'),
# ('B', 'B2'),
# ('B', 'B3')],
# names=['外层索引', '内层索引'])
from pandas import MultiIndex
# 根据数组列表创建一个 MultiIndex 类的对象
multi = MultiIndex.from_arrays(arrays = [['A','B','A','B','B'],['A1','A2','B1','B2','B3']],names = ['外层索引','内层索引'])
# 结果:
# MultiIndex([('A', 'A1'),
# ('B', 'A2'),
# ('A', 'B1'),
# ('B', 'B2'),
# ('B', 'B3')],
# names=['外层索引', '内层索引'])
from pandas import MultiIndex
numbers = [0,1,2]
colors = ['grenn','yellow']
# 根据数组创建一个 MultiIndex 类的对象
multi = MultiIndex.from_product(iterables = [numbers,colors] ,names = ['numbers','colors'])
# 结果:
# MultiIndex([(0, 'grenn'),
# (0, 'yellow'),
# (1, 'grenn'),
# (1, 'yellow'),
# (2, 'grenn'),
# (2, 'yellow')],
# names=['numbers', 'colors'])
扩展
在数学中,两个集合 X 和 Y 的笛卡尔积,又称直积,表示 X * Y,第一个对象是 X 的成员,而第二个对象是 Y 的所有可能有序对的其中一个成员。
创建有分层索引的对象
如果希望 Series 和 DataFrame 类对象拥有分层索引,最常见的方式是在 Series 类和 DataFrame 类的构造方法的 index 参数中传入一个嵌套列表。
多层索引格式:Series(values ,index = [[]])
multi = pd.Series([14530,14531,14532,14533,14534,14535,14536,14537],
index = [['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],
['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])
# 结果:
# 河北省 石家庄市 14530
# 唐山市 14531
# 邯郸市 14532
# 秦皇岛市 14533
# 河南省 郑州市 14534
# 开封市 14535
# 洛阳市 14536
# 新乡市 14537
multi = pd.DataFrame({'占地面积':[14530,13829,13829,12045,7813,7568,6239,15236]},
index = [['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],
['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])
# 结果:
# 占地面积
# 河北省 石家庄市 14530
# 唐山市 13829
# 邯郸市 13829
# 秦皇岛市 12045
# 河南省 郑州市 7813
# 开封市 7568
# 洛阳市 6239
# 新乡市 15236
使用分层索引获取数据
multi = pd.Series([14530,14531,14532,14533,14534,14535,14536,14537],
index = [['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],
['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])
# 结果:
# 河北省 石家庄市 14530
# 唐山市 14531
# 邯郸市 14532
# 秦皇岛市 14533
# 河南省 郑州市 14534
# 开封市 14535
# 洛阳市 14536
# 新乡市 14537
Series对象名['外层索引名']
multi['河北省']
# 结果:
# 石家庄市 14530
# 唐山市 14531
# 邯郸市 14532
# 秦皇岛市 14533
multi['河北省','唐山市']
# 结果:14531
multi[:,'开封市']
# 结果:14535
扩展:
直接获取内层数据:
Series对象名.iloc[索引]
df.loc([外层索引,内层索引])
去第二层所有的值:
df.xs(第二层值 ,level = '第二层名')
交换索引层级的顺序
交换索引层级的顺序是指交换外层索引和内层索引的位置。在 Pandas 中交换分层顺序的操作使用 swaplevel() 方法来完成。
multi = pd.Series([14530,14531,14532,14533,14534,14535,14536,14537],
index = [['河北省','河北省','河北省','河北省','河南省','河南省','河南省','河南省'],
['石家庄市','唐山市','邯郸市','秦皇岛市','郑州市','开封市','洛阳市','新乡市']])
# 结果:
# 河北省 石家庄市 14530
# 唐山市 14531
# 邯郸市 14532
# 秦皇岛市 14533
# 河南省 郑州市 14534
# 开封市 14535
# 洛阳市 14536
# 新乡市 14537
ser.swaplevel()
# 结果:
# 石家庄市 河北省 14530
# 唐山市 河北省 14531
# 邯郸市 河北省 14532
# 秦皇岛市 河北省 14533
# 郑州市 河南省 14534
# 开封市 河南省 14535
# 洛阳市 河南省 14536
# 新乡市 河南省 14537
分层索引排序
如果希望对具有分层索引的对象进行排序,则可以通过 sort_index() 方法实现,在使用他进行排序时,会优先按外层索引排序,然后再按照内层索引排序。
from pandas import DataFrame
df = DataFrame({'word':['a','b','d','e','f','k','d','s','l'],
'num':[1,2,4,5,3,2,6,2,3]},
index = [['A','A','A','C','C','C','B','B','B'],
[1,3,2,3,1,2,4,5,8]])
# 结果
# word num
# A 1 a 1
# 3 b 2
# 2 d 4
# C 3 e 5
# 1 f 3
# 2 k 2
# B 4 d 6
# 5 s 2
# 8 l 3
# 按索引排序
df.sort_index()
# 结果
# word num
# A 1 a 1
# 2 d 4
# 3 b 2
# B 4 d 6
# 5 s 2
# 8 l 3
# C 1 f 3
# 2 k 2
# 3 e 5
![[学习笔记 Day06]Python 数据分析与应用:数据分析库 Pandas 的使用-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250923154612655.png)

![[学习笔记 Day01]C++基础:简单的程序设计,始于梦想的开始!-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250922171813209.webp)
![[学习笔记 Day02]Vue基础:前端造梦,继续干!-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/09/20250919193418264.jpeg)


![[McMaster.NET 的使用] 打造自己的插件系统!-资源刺客](https://images.kodo.cdn.itdka.cn/wp-contents/uploads/2026/04/20260408212507422-科技感ENVI安装教程封面-1-scaled.png)
![[学习笔记 Day01]Git 版本控制系统:Git 命令的学习!-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2026/02/20260206152542723.png)
![[学习笔记 Day04]ASP.NET WEB 设计基础:让自己的程序飞向世界的每一个角落-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/08/20250827185617438.jpeg)
![[Dotnet-ef 工具] ORM 工具生成实体模型步骤及常见问题!-资源刺客](https://images.kodo.cdn.itdka.cn/wp-contents/uploads/2026/03/20260326200207417-818064be8e4c5751f8ce12720bbecbfb.jpeg)
![[自动化 + 手残党专属]宝塔安装AllinSSL证书管理教程-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2025/11/20251112122722716.png)




![[GitHub]Clawdbot-feishu:OpenClaw 的飞书集成插件-资源刺客](http://images.kodo.cdn.itdka.cn/wp-content/uploads/2026/02/20260214135015363.png)

暂无评论内容