第七章 数值操作(七)
7.1 数值替换
数值替换就是将数值A替换成B,可以用在异常值替换处理、缺失值填充处理中。主要有一对一替换、多对一替换、多对多替换三种替换方法。
7.1.1 一对一替换
一对一替换是将某一块区域中的一个值全部替换成另一个值 在Python中对某个值进行替换利用的是replace()方法,replace(A,B)表示将A替换成B。
df = pd. read_excel( r"D:\PythonFlie\test_1.xlsx" , header= 0 )
df
订单编号 客户姓名 唯一识别码 年龄 交易日期
0 A1 张旭 101 24 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
2 A3 孙峰 103 23 2018 - 10 - 03
3 A4 赵恒 104 204 2018 - 10 - 04
4 A5 赵恒 104 204 2018 - 08 - 12
df[ "年龄" ] . replace( 204 , 33 )
0 24
1 34
2 23
3 33
4 33
Name: 年龄, dtype: int64
有时候要对整个表进行替换,比如对全表中的缺失值进行替换,这个时候replace()方法就相当于fillna()方法了。 np.NaN是Python中对缺失值的一种表示方法
7.1.2 多对一替换
多对一替换就是把一块区域中的多个值替换成某一个值 在 Python 中实现多对一的替换比较简单,同样也是利用 replace()方法,replace([A,B],C)表示将A、B替换成C。
df. replace( [ 23 , 204 ] , 33 )
订单编号 客户姓名 唯一识别码 年龄 交易日期
0 A1 张旭 101 24 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
2 A3 孙峰 103 33 2018 - 10 - 03
3 A4 赵恒 104 33 2018 - 10 - 04
4 A5 赵恒 104 33 2018 - 08 - 12
7.1.3 多对多替换
多对多替换其实就是某个区域中多个一对一的替换 在Python中若想实现多对多的替换,同样是借助replace()方法,将替换值与待替换值用字典的形式表示,replace({“A”:“a”,“B”:“b”}表示用a替换A,用b替换B。
df. replace( { 24 : 34 , 204 : 24 } )
订单编号 客户姓名 唯一识别码 年龄 交易日期
0 A1 张旭 101 34 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
2 A3 孙峰 103 23 2018 - 10 - 03
3 A4 赵恒 104 24 2018 - 10 - 04
4 A5 赵恒 104 24 2018 - 08 - 12
7.2 数值排序
数值排序是按照具体数值的大小进行排序,有升序和降序 两种,升序就是数值由小到大排列,降序是数值由大到小排列。
7.2.1 按照一列数值进行排序
按照一列数值进行排序就是整个数据表都以某一列为准,进行升序或降序排列 在 Python 中我们若想按照某列进行排序,需要用到 sort_values()方法,在sort_values后的括号中指明要排序的列名,以及升序还是降序排列。
df. sort_values( by = [ "年龄" ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期
2 A3 孙峰 103 23 2018 - 10 - 03
0 A1 张旭 101 24 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
3 A4 赵恒 104 204 2018 - 10 - 04
4 A5 赵恒 104 204 2018 - 08 - 12
7.2.2 按照有缺失值的列进行排序
在Python中,当待排序的列中有缺失值时,可以通过设置na_position参数对缺失值的显示位置进行设置,默认参数值为last,可以不写,表示将缺失值显示在最后。
df. sort_values( by = [ "销售id" ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
1 A2 李刚 102 34 2018 - 10 - 02 1.0
2 A3 孙峰 103 23 2018 - 10 - 03 2.0
3 A4 赵恒 104 204 2018 - 10 - 04 3.0
4 A5 赵恒 104 204 2018 - 08 - 12 4.0
0 A1 张旭 101 24 2018 - 10 - 01 NaN
df. sort_values( by = [ "销售id" ] , na_position = "first" )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
0 A1 张旭 101 24 2018 - 10 - 01 NaN
1 A2 李刚 102 34 2018 - 10 - 02 1.0
2 A3 孙峰 103 23 2018 - 10 - 03 2.0
3 A4 赵恒 104 204 2018 - 10 - 04 3.0
4 A5 赵恒 104 204 2018 - 08 - 12 4.0
7.2.3 按照多列数值进行排序
按照多列数值排序是指同时依据多列数据进行升序、降序排列,当第一列出现重复值时按照第二列进行排序,当第二列出现重复值时按照第三列进行排序,以此类推。 在 Python 中实现按照多列进行排序,用到的方法同样是 sort_values(),只要在sort-values后的括号中以列表的形式指明要排序的多列列名及每列的排序方式即可。
df. sort_values( by = [ "年龄" , "销售id" ] , ascending = [ False , True ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
3 A4 赵恒 104 204 2018 - 10 - 04 3.0
4 A5 赵恒 104 204 2018 - 08 - 12 4.0
1 A2 李刚 102 34 2018 - 10 - 02 1.0
0 A1 张旭 101 24 2018 - 10 - 01 NaN
2 A3 孙峰 103 23 2018 - 10 - 03 2.0
7.3 数值排名
在Excel中用于排名的函数有RANK.AVG()和RANK.EQ()两个 RANK.AVG(number,ref,order) number表示待排名的数值,ref表示一整列数值的范围,order用来指明降序还是升序排名。当待排名的数值有重复值时,返回重复值的平均排名。 RANK.EQ(number,ref,order) RANK.EQ 的参数值与 RANK.AVG 的意思一样。当待排名的数值有重复值时,RANK.EQ返回重复值的最佳排名。 在Python中对数值进行排名,需要用到rank()方法。rank()方法主要有两个参数,一个是ascending,用来指明升序排列还是降序排列,默认为升序排列,和Excel中order的意思一致;另一个是method,用来指明待排列值有重复值时的处理情况。下表是参数method可取的不同参数值及说明。
df
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
0 A1 张旭 101 24 2018 - 10 - 01 1
1 A2 李刚 102 34 2018 - 10 - 02 2
2 A3 孙峰 103 23 2018 - 10 - 03 1
3 A4 赵恒 104 204 2018 - 10 - 04 2
4 A5 赵恒 104 204 2018 - 08 - 12 3
df[ "销售id" ] . rank( method = "average" )
0 1.5
1 3.5
2 1.5
3 3.5
4 5.0
Name: 销售id , dtype: float64
df[ "销售id" ] . rank( method = "first" )
0 1.0
1 3.0
2 2.0
3 4.0
4 5.0
Name: 销售id , dtype: float64
df[ "销售id" ] . rank( method = "min" )
0 1.0
1 3.0
2 1.0
3 3.0
4 5.0
Name: 销售id , dtype: float64
df[ "销售id" ] . rank( method = "max" )
0 2.0
1 4.0
2 2.0
3 4.0
4 5.0
Name: 销售id , dtype: float64
7.4 数值删除
7.4.1 删除列
在Python中,要删除某列,用到的是drop()方法,即在drop方法后的括号中指明要删除的列名或者列的位置,即第几列。 在drop方法后的括号中直接传入待删除列的列名,需要加一个参数axis,并让其参数值等于1,表示删除列。
df. drop( [ "销售id" ] , axis = 1 )
订单编号 客户姓名 唯一识别码 年龄 交易日期
0 A1 张旭 101 24 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
2 A3 孙峰 103 23 2018 - 10 - 03
3 A4 赵恒 104 204 2018 - 10 - 04
4 A5 赵恒 104 204 2018 - 08 - 12
df. drop( df. columns[ [ 3 , 4 ] ] , axis = 1 )
订单编号 客户姓名 唯一识别码 销售id
0 A1 张旭 101 1
1 A2 李刚 102 2
2 A3 孙峰 103 1
3 A4 赵恒 104 2
4 A5 赵恒 104 3
df. drop( columns = [ "销售id" ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期
0 A1 张旭 101 24 2018 - 10 - 01
1 A2 李刚 102 34 2018 - 10 - 02
2 A3 孙峰 103 23 2018 - 10 - 03
3 A4 赵恒 104 204 2018 - 10 - 04
4 A5 赵恒 104 204 2018 - 08 - 12
7.4.2 删除行
在Python中,要删除某些行用到的方法依然是drop(),与删除列类似的是,删除行也要指明行相关的信息。 在drop方法后的括号中直接传入待删除行的行名,并让axis参数值等于0,表示删除行。
df. drop( [ 0 , 1 ] , axis = 0 )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
2 A3 孙峰 103 23 2018 - 10 - 03 1
3 A4 赵恒 104 204 2018 - 10 - 04 2
4 A5 赵恒 104 204 2018 - 08 - 12 3
df. drop( df. index[ [ 0 , 1 ] ] , axis = 0 )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
2 A3 孙峰 103 23 2018 - 10 - 03 1
3 A4 赵恒 104 204 2018 - 10 - 04 2
4 A5 赵恒 104 204 2018 - 08 - 12 3
df. drop( index = [ 0 , 1 ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
2 A3 孙峰 103 23 2018 - 10 - 03 1
3 A4 赵恒 104 204 2018 - 10 - 04 2
4 A5 赵恒 104 204 2018 - 08 - 12 3
7.4.3 删除特定行
删除特定行一般指删除满足某个条件的行,我们前面的异常值删除算是删除特定的行。 在Python中删除特定行使用的方法有些特殊,我们不直接删除满足条件的值,而是把不满足条件的值筛选出来作为新的数据源,这样就把要删除的行过滤掉了。
df[ df[ "年龄" ] < 40 ]
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
0 A1 张旭 101 24 2018 - 10 - 01 1
1 A2 李刚 102 34 2018 - 10 - 02 2
2 A3 孙峰 103 23 2018 - 10 - 03 1
7.5 数值计数
数值计数就是计算某个值在一系列数值中出现的次数。 在Excel中实现数值计数,我们使用的是COUNTIF()函数,COUNTIF()函数用来计算某个区域中满足给定条件的单元格数目。 在Python中,要对某些值的出现次数进行计数,我们用到的方法是value_counts()。
df[ "销售id" ] . value_counts( )
1 2
2 2
3 1
Name: 销售id , dtype: int64
这些是值出现的绝对次数,还可以看一下不同值出现的占比,只需要给value_counts()方法传入参数normalize = True即可。
df[ "销售id" ] . value_counts( normalize = True )
1 0.4
2 0.4
3 0.2
Name: 销售id , dtype: float64
通过设置sort=False可以实现不按计数值降序排列。
df[ "销售id" ] . value_counts( normalize = True , ascending = True )
3 0.2
1 0.4
2 0.4
Name: 销售id , dtype: float64
7.6 唯一值获取
唯一值获取就是把某一系列值删除重复项以后的结果,一般可以将表中某一列认为是一系列值。 在Python中,我们要获取一列值的唯一值,整体思路与Excel的是一致的,先把某一列的值复制粘贴出来,然后用删除重复项的方法实现,关于删除重复项在前面讲过了,本节用另一种获取唯一值的方法unique()实现。
df[ "销售id" ] . unique( )
array( [ 1 , 2 , 3 ] , dtype= int64)
7.7 数值查找
数值查找就是查看数据表中的数据是否包含某个值或者某些值。 在Python中查看数据表中是否包含某个值用到的是isin()方法,而且可以同时查找多个值,只需要在isin方法后的括号中指明即可。
df[ "年龄" ] . isin( [ 24 , 22 ] )
0 True
1 False
2 False
3 False
4 False
Name: 年龄, dtype: bool
df. isin( [ 24 , 22 ] )
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id
0 False False False True False False
1 False False False False False False
2 False False False False False False
3 False False False False False False
4 False False False False False False
7.8 区间切分
区间切分就是将一系列数值分成若干份 在Python中对区间切分利用的是cut()方法,cut()方法有一个参数bins用来指明切分区间。
pd. cut( df[ "年龄" ] , bins = [ 0 , 3 , 6 , 10 ] )
0 ( 0 , 3 ]
1 ( 0 , 3 ]
2 ( 0 , 3 ]
3 ( 3 , 6 ]
4 ( 3 , 6 ]
5 ( 3 , 6 ]
6 ( 6 , 10 ]
7 ( 6 , 10 ]
8 ( 6 , 10 ]
9 ( 6 , 10 ]
Name: 年龄, dtype: category
Categories ( 3 , interval[ int64] ) : [ ( 0 , 3 ] < ( 3 , 6 ] < ( 6 , 10 ] ]
与cut()方法类似的还有qcut()方法,qcut()方法不需要事先指明切分区间,只需要指明切分个数,即你要把待切分数据切成几份,然后它就会根据待切分数据的情况,将数据切分成事先指定的份数,依据的原则就是每个组里面的数据个数尽可能相等。
pd. qcut( df[ "年龄" ] , 5 )
0 ( 0.999 , 2.8 ]
1 ( 0.999 , 2.8 ]
2 ( 2.8 , 4.6 ]
3 ( 2.8 , 4.6 ]
4 ( 4.6 , 6.4 ]
5 ( 4.6 , 6.4 ]
6 ( 6.4 , 8.2 ]
7 ( 6.4 , 8.2 ]
8 ( 8.2 , 10.0 ]
9 ( 8.2 , 10.0 ]
Name: 年龄, dtype: category
Categories ( 5 , interval[ float64] ) : [ ( 0.999 , 2.8 ] < ( 2.8 , 4.6 ] < ( 4.6 , 6.4 ] < ( 6.4 , 8.2 ] < ( 8.2 , 10.0 ] ]
7.9 插入新的行或列
在特定的位置插入行或者列也是比较常用的操作。具体的插入操作有两个关键要素,一个是在哪插入,另一个是插入什么。 在Python中没有专门用来插入行的方法,可以把待插入的行当作一个新的表,然后将两个表在纵轴方向上进行拼接。关于表拼接在后面的章节会讲。 在Python中插入一个新的列用到的方法是insert(),在insert方法后的括号中指明要插入的位置、插入后新列的列名,以及要插入的数据。
df. insert( 2 , "商品类别" , [ "cat01" , "cat02" , "cat03" , "cat04" , "cat05" ] )
df
订单编号 客户姓名 商品类别 唯一识别码 年龄 交易日期 销售id
0 A1 张旭 cat01 101 24 2018 - 10 - 01 1
1 A2 李刚 cat02 102 34 2018 - 10 - 02 2
2 A3 孙峰 cat03 103 23 2018 - 10 - 03 1
3 A4 赵恒 cat04 104 204 2018 - 10 - 04 2
4 A5 赵恒 cat05 104 204 2018 - 08 - 12 3
df[ "商品类别" ] = [ "cat01" , "cat02" , "cat03" , "cat04" , "cat05" ]
df
订单编号 客户姓名 唯一识别码 年龄 交易日期 销售id 商品类别
0 A1 张旭 101 24 2018 - 10 - 01 1 cat01
1 A2 李刚 102 34 2018 - 10 - 02 2 cat02
2 A3 孙峰 103 23 2018 - 10 - 03 1 cat03
3 A4 赵恒 104 204 2018 - 10 - 04 2 cat04
4 A5 赵恒 104 204 2018 - 08 - 12 3 cat05
7.10 行列互换
所谓的行列互换(又称转置)就是将行数据转换到列方向上,将列数据转换到行方向上。 在 Python 中,我们直接在源数据表的基础上调用.T 方法即可得到源数据表转置后的结果。对转置后的结果再次转置就会回到原来的结果
df. T
0 1 2 3 4
订单编号 A1 A2 A3 A4 A5
客户姓名 张旭 李刚 孙峰 赵恒 赵恒
唯一识别码 101 102 103 104 104
年龄 24 34 23 204 204
交易日期 2018 - 10 - 01 00 : 00 : 00 2018 - 10 - 02 00 : 00 : 00 2018 - 10 - 03 00 : 00 : 00 2018 - 10 - 04 00 : 00 : 00 2018 - 08 - 12 00 : 00 : 00
销售id 1 2 1 2 3
商品类别 cat01 cat02 cat03 cat04 cat05
7.11 索引重塑
所谓的索引重塑就是将原来的索引进行重新构造。典型的DataFrame结构的表如下表所示。 我们把数据从表格型数据转换到树形数据的过程叫重塑,这种操作在Excel中没有,在Python用到的方法是stack(),示例代码如下所示。
df. stack( )
0 订单编号 A1
客户姓名 张旭
唯一识别码 101
年龄 24
交易日期 2018 - 10 - 01 00 : 00 : 00
销售id 1
商品类别 cat01
1 订单编号 A2
客户姓名 李刚
唯一识别码 102
年龄 34
交易日期 2018 - 10 - 02 00 : 00 : 00
销售id 2
商品类别 cat02
2 订单编号 A3
客户姓名 孙峰
唯一识别码 103
年龄 23
交易日期 2018 - 10 - 03 00 : 00 : 00
销售id 1
商品类别 cat03
3 订单编号 A4
客户姓名 赵恒
唯一识别码 104
年龄 204
交易日期 2018 - 10 - 04 00 : 00 : 00
销售id 2
商品类别 cat04
4 订单编号 A5
客户姓名 赵恒
唯一识别码 104
年龄 204
交易日期 2018 - 08 - 12 00 : 00 : 00
销售id 3
商品类别 cat05
dtype: object
与stack()方法相对应的方法是unstack()方法,stack()方法是将表格型数据转化为树形数据,而unstack()方法是将树形数据转为表格型数据,示例代码如下所示。
df. unstack( )
7.12 长宽表转换
长宽表转换就是将比较长(很多行)的表转换为比较宽(很多列)的表,或者将比较宽的表转化为比较长的表。
7.12.1 宽表转换为长表
Python中要实现这种转换有两种方法,一种是stack()方法,另一种是melt()方法。
df = pd. read_excel( r"D:\PythonFlie\test_3.xlsx" , header= 0 )
df
company name sale2013 sale2014 sale2015 sale2016
0 apple 苹果 5000 5050 5050 5050
1 google 谷歌 3500 2800 2300 4500
2 facebook 脸书 2300 1200 6700 2100
df. set_index( [ "company" , "name" ] )
sale2013 sale2014 sale2015 sale2016
company name
apple 苹果 5000 5050 5050 5050
google 谷歌 3500 2800 2300 4500
facebook 脸书 2300 1200 6700 2100
df. set_index( [ "company" , "name" ] ) . stack( )
company name
apple 苹果 sale2013 5000
sale2014 5050
sale2015 5050
sale2016 5050
google 谷歌 sale2013 3500
sale2014 2800
sale2015 2300
sale2016 4500
facebook 脸书 sale2013 2300
sale2014 1200
sale2015 6700
sale2016 2100
dtype: int64
df. set_index( [ "company" , "name" ] ) . stack( ) . reset_index( )
company name level_2 0
0 apple 苹果 sale2013 5000
1 apple 苹果 sale2014 5050
2 apple 苹果 sale2015 5050
3 apple 苹果 sale2016 5050
4 google 谷歌 sale2013 3500
5 google 谷歌 sale2014 2800
6 google 谷歌 sale2015 2300
7 google 谷歌 sale2016 4500
8 facebook 脸书 sale2013 2300
9 facebook 脸书 sale2014 1200
10 facebook 脸书 sale2015 6700
11 facebook 脸书 sale2016 2100
df. melt( id_vars = [ "company" , "name" ] , var_name = "year" , value_name = "sale" )
company name year sale
0 apple 苹果 sale2013 5000
1 google 谷歌 sale2013 3500
2 facebook 脸书 sale2013 2300
3 apple 苹果 sale2014 5050
4 google 谷歌 sale2014 2800
5 facebook 脸书 sale2014 1200
6 apple 苹果 sale2015 5050
7 google 谷歌 sale2015 2300
8 facebook 脸书 sale2015 6700
9 apple 苹果 sale2016 5050
10 google 谷歌 sale2016 4500
11 facebook 脸书 sale2016 2100
melt中的id_vars参数用于指明宽表转换到长表时保持不变的列,var_name参数表示原来的列索引转化为“行索引”以后对应的列名,value_name表示新索引对应的值的列名。 注意,这里的“行索引”是有双引号的,它并非实际行索引,只是类似实际的行索引。
7.12.2 长表转换为宽表
将长表转化为宽表就是宽表转化为长表的逆过程。常用的方法就是数据透视表,关于数据透视表的使用我们将在10.2节进行详细讲解
7.13 apply()与applymap()函数
我们在Python基础知识部分讲过一个Python的高级特性map()函数,map()函数是对一个序列中的所有元素执行相同的函数操作。 在DataFrame中与map()函数类似的函数有两个,一个是apply()函数,另一个是applymap()函数。函数apply()和applymap()都需要与匿名函数lambda结合使用。 apply()函数主要用于对DataFrame中的某一column或row中的元素执行相同的函数操作。
df[ "sale2013" ] . apply ( lambda x: x+ 1 )
0 5001
1 3501
2 2301
Name: sale2013, dtype: int64
applymap()函数用于对DataFrame中的每一个元素执行相同的函数操作。
df. applymap( lambda x: x+ 1 )
年龄
0 2
1 3
2 4
3 5
4 6
5 7
6 8
7 9
8 10
9 11