[学习笔记 Day06]Python 数据分析与应用:数据分析库 Pandas 的使用

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
常见的 Index 子类

索引对象主要有两种特性:

  • 不可变性:
    索引对象一旦创建是不可以直接修改的,即索引的值是固定不变的,这样做能够维护从索引到数据的唯一映射关系,保证 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(默认值)、ffillpadbfillbackfillnearset 等值)
    • 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 ...]

参数可以接收多种形式的对象,常见的情况如下:

  1. 单个标签索引
  2. 标签索引构成的列表或数组,如:[‘a’,’b’,’c’]、[‘col1′,’col2’] 等。
  3. 基于标签索引的切片,如:’a’:’c’、’two’:’four’ 等。
  4. 布尔类型的列表、数组或 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 ]

参数可以接收多种形式的对象,常见的情况主要有一下几种:

  1. 单个位置索引
  2. 位置索引构成的列表或数组,如 [0,1,2] 等
  3. 基于位置索引的切片,如 0:2、2:5 等
  4. 布尔类型的列表、数组或 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)
  • 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 类的对象
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

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容