开发者学堂课程【大数据 Spark 2020版(知识精讲与实战演练)第三阶段:缺失值处理_null&;NaN_读取文件】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/690/detail/12083
缺失值处理_null&;NaN_读取文件
内容介绍:
一、缺失值介绍
二、DataFrameNaFunctions
三、如何使用 SparkSQL 处理 null 和 NaN
一、缺失值介绍
缺失值大概分为两类,一类是 NaN,null,直接表达没有值的含义;另一类是不规则字符串,比如空字符串“NA”,“NULL”
缺失值处理也是分为两类:一类,就是直接处理 null 这样的缺失值,还有一类,是对于字符串的处理。
接下来,我们要针对于这两类不同类别的缺失值进行单独的讲解,通过我们这一个小结,希望大家了解这两种缺失值如何处理。
我们在处理这种缺失值时,就需要有一些步骤的讲解,首先,我们要介绍 SparkSQL 当中提供的工具,之后介绍如何读取数据,最终是缺失值如何处理。缺失值处理方式,一种是丢弃包含缺失值的行,另一只种是替换初始值。
缺失值的处理的三个步骤:第一个步骤,了解 spark 做了什么事情,帮助处理缺失值;第二步骤,了解在读取数据时,怎么把值读成 NULL;还有一种缺失值处理是通过第三个步骤,让大家了解如何处理缺失值,处理时使用的是 spark 提供的工具。
二、DataFrameNaFunctions
spark 提供的工具:DataFrameNaFunctions
DataFrameNaFunctions 使用 Dataset 的 na 函数来获取
val df = .. val naFunc : DataFrameNaFunctions = df.na
当数据集中出现缺失值的时候,大致有两种处理方式,一个是丢弃,一个是替换为某值, DataFrameNaFunctions 中包含一系列针对空值数据的方案:
·DataFrameNaFunctions.drop 可以在当某行中包含 null 或 NaN 的时候丢弃此行
·DataFrameNaFunctions.fill 可以在将 null 和 NaN 充为其它值
·DataFrameNaFunctions . replace 可以把 null 或 NaN 替换为其它值,但是和 filll 略有一些不同,这个方法针对值来进行替换
DataFrameNaFunctions 是缺失值处理的框架
DataFrameNaFunctions 是以一个对象的形式提供的,第一点,我们来说一说如何创建。
①创建:df.na
②功能:
可以直接使用 df.na,通过这样的一个 NA 的属性,我们能够获取一个 DataFrameNaFunctions 的对象。我们可以看到,拿到了一个 naf,这个 naf 的类型是 DataFrameNaFunctions。
DataFrameNaFunctions 提供的功能,一个是直接使用 naf.drop…去掉缺失值;二是可以使用 naf.fill...进行缺失值填充。所以我们在进行缺失值处理的时候,假设 dataframe 当中有缺失值,如果要把这个缺失值给去掉,应该怎么写?使用 df.na.drop;如果进行填充,怎么填充?
可以使用 df.na.fill。这个 NA 返回的并不是一个 dataframe,而是一个小框架,必须要处理小框架,要调用 drop 或者 fill,或者 replace,replac 是替换。要调用这三个方法才能再返回给 dataframe,从而进行相应的展示或者写入某一个文件,这就是这个框架提供的功能。
三、如何使用 SparkSQL 处理 null 和 NaN
首先是将数据读取出来:
为缺失值处理创建新的 Class,Class 名称为 NullProcessor
之后创建方法,def nullAndNaN():Unit = {
总结步骤,首先第一步是创建 sparksession;第二步是导入一个新的数据集;第三步,导入数据集后,去读取数据集;第四步,丢弃;第五步填充。
代码:
import org.apache.spark.sql.Sparksession
import org.junit.Test
class Nullprocessor {
@Test
def nul1AndNaN() : unit = {
// 1.创建 sparksession
val spark = sparksession.builder()
master( master = "local[6]")
appName( name = "null processor")
getorcreate()
// 2.导入数据集
将 Beijingpm_with_nan.csv 文件拷贝到目录中即可。
注:导入的文件与之前不同,列减少并且列名变为小写;原始文件的缺失值是 NA,改文件缺失值是 NAN,
如下图:
// 3.读取数据集
1.通过 saprk-csv 自动的推断类型来读取,推断数字的时候会将 NaN 推断为字符串
spark.read
option( "header", true)
option ( "inferschema " , true)
csv(... )
打开 Beijingpm_with_nan.csv 文件,这个文件当中,比如说 2010 明显是一个数字,那后面的东西是?如果我们直接通过类型推断,通过这个 spark-csv 提供的类型推断的功能,后面大家觉得应该怎么推断?
我们最后一列的前半部分都是 NAN,后半部分,会有一些具体的值,这个值是 double。所以,如果要让它自动推断,使用 spark-csv 自动推断,那么如果读不成这个 double,可能会把这个 double 当成字符串去处理。
这种处理有一个问题:如果有一些数据,比如在推断数字时,会将这种值推断为字符串,整个列都会变成字符串,这种方式并不适合我们。那么接下来,我们再来看第二种读取方式。
2.直接读取字符串,在后续的操作中使用 map 算子转类型
spark.read.csv( ).map( row => row. . . )
接下来讲第三种方式,假如说某一列的某一些数值是 NAN,第一种方式,会把 NAN 这种列推断为字符串,假如说指定 Schema,靠指定 Schema 不要自动推断,那么就可以把这个 NAN 转成 double 类型的 NAN,继续来看我们第三种方式啊,第三种方式,是我们今天要采用的方式。
// 3.指定 schema,不要自动推断
val schema = structType(
List(
structField("id", LongType),
structField( "year", IntegerType),
structField( "month", IntegerType),
structField("day" , IntegerType),
structField("season”,IntegerType) ,
structField( "pm" , DoubleType)
)
)
spark.read
option( "header", value = true)
schema( schema)
csv( path = "dataset/beijingpm_with_nan.csv")
通过这种指定 scheme 的形式,就可以在读取数据集的时候指定某一列是 double,如果出现 NAN,那么 Spark-csv 会自动的将 NAN 转成 double 下的 NAN。
Double 下的 NAN 就不是一个字符串,跟读出来的“NAN”是有区别。所以,我们通过这种方式,就可以把它转成 double 下的 NAN,代表它不是一个数字,那么接下来,我们就去为其创建一个 source,之后 show(),查看其中的内容,。
val sourceDF = spark.read
option("header", value = true).schema(schema)
csv( path = "dataset/beijingpm_with_nan.csv")
sourceDF . show(
运行这段代码:
根据上图,读取数据完成并且没有任何问题。

