开发者学堂课程【大数据 Spark 2020版(知识精讲与实战演练)第三阶段:缺失值处理_null&NaN_处理】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/690/detail/12084
缺失值处理_null&NaN_处理
内容介绍:
一、丢弃包含 null 和 NaN 的行
二、填充包含 null 和 NaN 的列
一、丢弃包含 null 和 NaN 的行
当某行数据所有值都是 null 或者 NaN 的时候丢弃此行
df.na. drop ( "all" ).show ( )
当某行中特定列所有值都是 null 或者 NaN 的时候丢弃此行
df.na. drop ( "all", List ( "pm" , "id" ) ).show ( )
当某行数据任意─个字段为 null 或者 NaN 的时候丢弃此行
df.na.drop( ).show ( )
df.na.drop ( "any" ) .show ( )
当某行中特定列任意一个字段为 null 或者 NaN 的时候丢弃此行
df.na.drop ( List( "pm" , "id" ) ).show ( )
df.na . drop ( "any" , List ( "pm" , "id" ) ).show ( )
代码:
// 4.丢弃
//2019,12,12,60.0
//规则:
//1. any,,只有有一个 NaN 就丢弃
//2. alL,所有数据都是 NaN 的行才丢弃
//3.某些列的规则
杜撰出来一行数据 2019, 12,12,PM 值为 60.0,之后看规则,大致有三种规则,要丢弃这个数据,需要有一些判断,第一种规则,称之为 any;第二种规则,all;第三种,针对某些列的规则。我们先看第一种 any,这一行数据里,有任何一个数据为 NAN,那就丢弃,这叫做 any。
All,所有都是 NAN 的行,才丢弃。这两种方式,老师个人觉得第一种方式会更实用一些,因为这个数据集,它是由成千上万上亿条数据组成的,比如说前 100 行是 NAN,,后面不是 NAN,那么,在针对于这个数据集的整体来进行操作的时候,这些 NAN 就会对整个这一列的数据的特征造成一些影响,所以第一种方式可能会常见一些。
但是第二种方式,也明显是有它的应用场景,比如说有一些数据,这一行数据所有的列全都是 NAN 的时候,这一行数据才丧失它的意义,只要有任何一列数据不是 NAN,那么这一行数据肯定会有一些意义。
假如针对某些列,针对于这些列有任何一个 NAN 就丢弃,针对于另外一些列,它所有的都会 NAN,才丢弃,比如说这一行数据:2019,12,12,NAN 去看,前面 2019,12,12 这是日期数据,那么这些日期数据只要有任何一列,比如说 12 这一类,只要有任何一列是 NAN,或者是 null 也行,null 和 NAN 都是缺失值,只要有任何一列为缺失值,那么这一条数据都找不着日期。这条数据如果是一个时间序列的数据,那么这条数据就已经丧失意义了,如果是这样,这条数据就丢弃。
但是,只是针对于 2019,12,12 这三列,是 any;但是针对于后面,假如说有很多个 PM,只要有任何一个 PM 值不为 NAN,那么依然是有意义的,所以,对于后面,就是 all。
为什么使用 pm 相关的数据集:首先,它里面包含了两种常见的数据处理的场景,第一种是它包含时间,第二就是它包含一些 PM 值,这些 PM 值是 double 型的,所以,针对 double 数据的处理项目,比如说统计销量,统计平均的营业额,这个数据集的特征比较多,所以才采用它。
接下来实现以上三种规则:
//1. any,只有有一个 NaN 就丢弃
sourceDF.na.drop( how = "any" ).show()
注:na 返回的是 DataFrameNaFunctions,故通过 na 进行 show()是没有意义的,必须要先处理缺失值,可以使用 drop。
sourceDF.na.drop( ).show( )
//2. alL,所有数据都是 NaN 的行才丢弃
sourceDF.na.drop( how = "all" ).show()
//3.某些列的规则
sourceDF.na.drop( how = "any", List("year" ,"month","day" ,"hour" )). show()
二、填充包含 null 和 NaN 的列
代码:
// 5.填充
//规则:
//1. 针对所有列数据进行默认值填充
sourceDF.na.fill( value = 0) .show()
//2.针对特定列填充
sourceDF.na.fill( value = 0,List("year","month" ) ) .show()
但是数据集这段代码当中有一个十分常见的错误,先运行这段代码,稍后指出错误:
通过运行结果发现:sourceDF.na.drop( how = "any" ).show()
sourceDF.na.drop( ).show( )
sourceDF.na.drop( how = "all" ).show()
这三行代码运行之后的数据集相同,代表数据处理失败。
经过分析:发现 PM 列数据不对,如果指定了 Schema,首先检查 Schema:
val schema = structType(
List(
structField("id", LongType),
structField( "year", IntegerType),
structField( "month", IntegerType),
structField("day" , IntegerType),
structField("hour" , IntegerType),
structField("season”,IntegerType) ,
structField( "pm" , DoubleType)
)
)
发现:Schema 当中是 id,year,month,season 和 pm,但数据当中有一个 hour,所以,简单来说就是在读数据的时候读错了,只要在 day 后面加上 structField("hour" , IntegerType)。
再去运行一下查看其结果。继续再往下看,上图是第一行的结果,是针对于所有的这个列进行 NAN 的这个过滤,只要有任何一个列为 NAN,就去掉它。第二个结果和第一个是一样的,因为都是 any。
第三个结果:包含了一系列 NAN 的值
第四个结果和第三个的结果相似。
接下来是填充:
针对所有数列进行默认值填充,发现最后一列的 pm 值被填充为 0
针对于特定列的填充:
这时数据时没有问题的,以上就是针对缺失值的处理,第一种方法是丢弃,第二种是填充。