SparkSQL处理缺失值

一:缺失值的处理方式

1.常见的缺失值有两种

1.null, NaN 等特殊类型的值, 某些语言中 null 可以理解是一个对象, 但是代表没有对象, NaN 是一个数字, 可以代表不是数字
针对这一类的缺失值, Spark 提供了一个名为 DataFrameNaFunctions 特殊类型来操作和处理

2.“Null”, “NA”, " " 等解析为字符串的类型, 但是其实并不是常规字符串数据
针对这类字符串, 需要对数据集进行采样, 观察异常数据, 总结经验, 各个击破

2.常见的三种处理方式

1.丢弃/过滤
DataFrame.na.drop()

2.填充
DataFrame.na.fill()

3.替换
DataFrame.na.replace()

3.丢弃规则

1.any 一行中有任何一个是NaN/null就丢弃
2.all 只有一行中所有的都是NaN/null才丢弃
3.某些规则 针对某些列有NaN/null,是否丢弃该列

4.填充规则

1.针对所有列进行默认填充
2.针对特定的列

二:使用SparkSQL处理null 和NaN

class demo01 {

  private val spark: SparkSession = SparkSession.builder().master("local[4]").appName("nan").getOrCreate()
  import spark.implicits._

  @Test
  def demo01(): Unit ={
    //因为自动推断字段类型可能识别NAN为String类型,不方便,这里使用指定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)
    ))

    //1.读取数据集
    val source = spark.read
      .option("header", true)
      .schema(schema)
      .csv("dataset/beijingpm_with_nan.csv")

    //2.第一种方式:丢弃
    /**
      * 丢弃规则:
      * 1.any  一行中有任何一个是NaN/null就丢弃
      * 2.all  只有一行中所有的都是NaN/null才丢弃
      * 3.某些规则 针对某些列有NaN/null,是否丢弃该列
      */

    source.na.drop("any").show()  //任何出现NaN/null就丢弃该行
    source.na.drop().show() //同上.默认any
    source.na.drop("all").show() //当所有的行都是NaN/null才丢弃
    source.na.drop("any",List("year","month","day","hour")) //针对特定列任意出现NaN/null就丢弃该行

    //3.第二种方式:填充
    /**
      * 填充规则
      * 1.针对所有列进行默认填充
      * 2.针对特定的列
      */

    source.na.fill(0).show()  //针对所有列填充为0
    source.na.fill(0,List("year","month")).show() //只填充具体列

  }

}

程序运行结果:

原始数据:

+---+----+-----+---+----+------+---+
| id|year|month|day|hour|season| pm|
+---+----+-----+---+----+------+---+
|  1|2010|    1|  1|   0|     4|NaN|
|  2|2010|    1|  1|   1|     4|NaN|
|  3|2010|    1|  1|   2|     4|NaN|
|  4|2010|    1|  1|   3|     4|NaN|
|  5|2010|    1|  1|   4|     4|NaN|
|  6|2010|    1|  1|   5|     4|NaN|
|  7|2010|    1|  1|   6|     4|NaN|
|  8|2010|    1|  1|   7|     4|NaN|
|  9|2010|    1|  1|   8|     4|NaN|
| 10|2010|    1|  1|   9|     4|NaN|
+---+----+-----+---+----+------+---+
only showing top 10 rows

(any规则)丢弃后的结果:

+-----+----+-----+---+----+------+----+
|   id|year|month|day|hour|season|  pm|
+-----+----+-----+---+----+------+----+
|26695|2013|    1| 17|   6|     4|25.0|
|26696|2013|    1| 17|   7|     4|22.0|
|26697|2013|    1| 17|   8|     4|20.0|
|26698|2013|    1| 17|   9|     4|24.0|
|26699|2013|    1| 17|  10|     4|27.0|
|26700|2013|    1| 17|  11|     4|29.0|
|26701|2013|    1| 17|  12|     4|31.0|
|26702|2013|    1| 17|  13|     4|27.0|
|26703|2013|    1| 17|  14|     4|39.0|
|26704|2013|    1| 17|  15|     4|53.0|
+-----+----+-----+---+----+------+----+
only showing top 10 rows

替换后的结果:

+---+----+-----+---+----+------+---+
| id|year|month|day|hour|season| pm|
+---+----+-----+---+----+------+---+
|  1|2010|    1|  1|   0|     4|0.0|
|  2|2010|    1|  1|   1|     4|0.0|
|  3|2010|    1|  1|   2|     4|0.0|
|  4|2010|    1|  1|   3|     4|0.0|
|  5|2010|    1|  1|   4|     4|0.0|
|  6|2010|    1|  1|   5|     4|0.0|
|  7|2010|    1|  1|   6|     4|0.0|
|  8|2010|    1|  1|   7|     4|0.0|
|  9|2010|    1|  1|   8|     4|0.0|
| 10|2010|    1|  1|   9|     4|0.0|
+---+----+-----+---+----+------+---+
only showing top 10 rows

三:SparlSQL处理异常字符串(NA / Null)

class demo02 {
  private val spark: SparkSession = SparkSession.builder().master("local[4]").appName("nan").getOrCreate()
  import spark.implicits._

  @Test
  def demo01(): Unit ={
    val source = spark.read
      .option("header", true)
      .option("inferSchema", true)
      .csv("dataset/BeijingPM20100101_20151231.csv")

    source.show(10)

    //1.丢弃
    //只获取 不为 =!= "NA" 的数据
    source.where('PM_Dongsi =!= "NA").show(10)

    //2.替换
      //2.1直接替换
    //想要使用when,就需要导入functions的隐式转换
    import org.apache.spark.sql.functions._

    val df1 = source.select(
      cols = 'No as "id", 'year, 'month, 'day, 'hour, 'season,
      //如果东四 等于 NA,就替换成 Double类型的NaN (NA是字符串类型,但是NaN是Double类型的 not a number,两者类型不一致)
      when('PM_Dongsi === "NA", Double.NaN)
        //还需要统一该列的其他数据的类型
        .otherwise('PM_Dongsi cast DoubleType)
        //再指定新的列名
        .as("pm")
    )
    df1.show(10)
    df1.printSchema()
    
      //2.2使用df.na.replace("指定列",Map("原始数据"->"替换后的数据"))进行替换,但是Map替换的方式类型不能变
    //注意: Map()转换的时候原类型和转换后的类型必须一致
    val df2 = source.na.replace(
      "PM_Dongsi", Map("NA" -> "NaN", "Null" -> "null")
    )
    df2.show(10)
    df2.printSchema()


  }
}

程序运行结果

原始数据:

+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
| No|year|month|day|hour|season|PM_Dongsi|PM_Dongsihuan|PM_Nongzhanguan|PM_US_Post|DEWP|HUMI|PRES|TEMP|cbwd|  Iws|precipitation|Iprec|
+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
|  1|2010|    1|  1|   0|     4|       NA|           NA|             NA|        NA| -21|  43|1021| -11|  NW| 1.79|            0|    0|
|  2|2010|    1|  1|   1|     4|       NA|           NA|             NA|        NA| -21|  47|1020| -12|  NW| 4.92|            0|    0|
|  3|2010|    1|  1|   2|     4|       NA|           NA|             NA|        NA| -21|  43|1019| -11|  NW| 6.71|            0|    0|
|  4|2010|    1|  1|   3|     4|       NA|           NA|             NA|        NA| -21|  55|1019| -14|  NW| 9.84|            0|    0|
|  5|2010|    1|  1|   4|     4|       NA|           NA|             NA|        NA| -20|  51|1018| -12|  NW|12.97|            0|    0|
|  6|2010|    1|  1|   5|     4|       NA|           NA|             NA|        NA| -19|  47|1017| -10|  NW| 16.1|            0|    0|
|  7|2010|    1|  1|   6|     4|       NA|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|19.23|            0|    0|
|  8|2010|    1|  1|   7|     4|       NA|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|21.02|            0|    0|
|  9|2010|    1|  1|   8|     4|       NA|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|24.15|            0|    0|
| 10|2010|    1|  1|   9|     4|       NA|           NA|             NA|        NA| -20|  37|1017|  -8|  NW|27.28|            0|    0|
+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
only showing top 10 rows

丢弃后的结果:
PM_Dongsi 这一列不再出现 NA 等非法字符

+-----+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
|   No|year|month|day|hour|season|PM_Dongsi|PM_Dongsihuan|PM_Nongzhanguan|PM_US_Post|DEWP|HUMI|PRES|TEMP|cbwd|  Iws|precipitation|Iprec|
+-----+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
|26695|2013|    1| 17|   6|     4|       25|           NA|             20|        34| -17|  56|1038| -10|  NW| 4.92|            0|    0|
|26696|2013|    1| 17|   7|     4|       22|           NA|             20|        33| -16|  52|1039|  -8|  NE| 4.92|            0|    0|
|26697|2013|    1| 17|   8|     4|       20|           NA|             27|        33| -16|  45|1040|  -6|  NE| 8.94|            0|    0|
|26698|2013|    1| 17|   9|     4|       24|           NA|             28|        34| -16|  38|1040|  -4|  NE|12.07|            0|    0|
|26699|2013|    1| 17|  10|     4|       27|           NA|             15|        38| -16|  35|1040|  -3|  NE|16.09|            0|    0|
|26700|2013|    1| 17|  11|     4|       29|           NA|             17|        38| -15|  33|1040|  -1|  NE|20.11|            0|    0|
|26701|2013|    1| 17|  12|     4|       31|           NA|             31|        41| -17|  26|1038|   0|  NE|23.24|            0|    0|
|26702|2013|    1| 17|  13|     4|       27|           NA|             18|        37| -18|  21|1037|   2|  NW| 1.79|            0|    0|
|26703|2013|    1| 17|  14|     4|       39|           NA|             24|        45| -18|  21|1036|   2|  cv| 0.89|            0|    0|
|26704|2013|    1| 17|  15|     4|       53|           NA|             48|        71| -17|  21|1035|   3|  SE| 1.79|            0|    0|
+-----+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
only showing top 10 rows

第一种替换方式的结果:和转换后的Schema信息

+---+----+-----+---+----+------+---+
| id|year|month|day|hour|season| pm|
+---+----+-----+---+----+------+---+
|  1|2010|    1|  1|   0|     4|NaN|
|  2|2010|    1|  1|   1|     4|NaN|
|  3|2010|    1|  1|   2|     4|NaN|
|  4|2010|    1|  1|   3|     4|NaN|
|  5|2010|    1|  1|   4|     4|NaN|
|  6|2010|    1|  1|   5|     4|NaN|
|  7|2010|    1|  1|   6|     4|NaN|
|  8|2010|    1|  1|   7|     4|NaN|
|  9|2010|    1|  1|   8|     4|NaN|
| 10|2010|    1|  1|   9|     4|NaN|
+---+----+-----+---+----+------+---+
only showing top 10 rows

PM_Dongsi  这一列的额数据类型由原来的 String类型转换成 Double类型

root
 |-- id: integer (nullable = true)
 |-- year: integer (nullable = true)
 |-- month: integer (nullable = true)
 |-- day: integer (nullable = true)
 |-- hour: integer (nullable = true)
 |-- season: integer (nullable = true)
 |-- pm: **double** (nullable = true)

replace的替换方式的结果,使用Map进行指定字段内的多种类型的不同替换方式

+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
| No|year|month|day|hour|season|PM_Dongsi|PM_Dongsihuan|PM_Nongzhanguan|PM_US_Post|DEWP|HUMI|PRES|TEMP|cbwd|  Iws|precipitation|Iprec|
+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
|  1|2010|    1|  1|   0|     4|      NaN|           NA|             NA|        NA| -21|  43|1021| -11|  NW| 1.79|            0|    0|
|  2|2010|    1|  1|   1|     4|      NaN|           NA|             NA|        NA| -21|  47|1020| -12|  NW| 4.92|            0|    0|
|  3|2010|    1|  1|   2|     4|      NaN|           NA|             NA|        NA| -21|  43|1019| -11|  NW| 6.71|            0|    0|
|  4|2010|    1|  1|   3|     4|      NaN|           NA|             NA|        NA| -21|  55|1019| -14|  NW| 9.84|            0|    0|
|  5|2010|    1|  1|   4|     4|      NaN|           NA|             NA|        NA| -20|  51|1018| -12|  NW|12.97|            0|    0|
|  6|2010|    1|  1|   5|     4|      NaN|           NA|             NA|        NA| -19|  47|1017| -10|  NW| 16.1|            0|    0|
|  7|2010|    1|  1|   6|     4|      NaN|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|19.23|            0|    0|
|  8|2010|    1|  1|   7|     4|      NaN|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|21.02|            0|    0|
|  9|2010|    1|  1|   8|     4|      NaN|           NA|             NA|        NA| -19|  44|1017|  -9|  NW|24.15|            0|    0|
| 10|2010|    1|  1|   9|     4|      NaN|           NA|             NA|        NA| -20|  37|1017|  -8|  NW|27.28|            0|    0|
+---+----+-----+---+----+------+---------+-------------+---------------+----------+----+----+----+----+----+-----+-------------+-----+
only showing top 10 rows


PM_Dongsi 替换后的类型还是String类型

root
 |-- No: integer (nullable = true)
 |-- year: integer (nullable = true)
 |-- month: integer (nullable = true)
 |-- day: integer (nullable = true)
 |-- hour: integer (nullable = true)
 |-- season: integer (nullable = true)
 |-- PM_Dongsi: **string** (nullable = true)
 |-- PM_Dongsihuan: string (nullable = true)
 |-- PM_Nongzhanguan: string (nullable = true)
 |-- PM_US_Post: string (nullable = true)
 |-- DEWP: string (nullable = true)
 |-- HUMI: string (nullable = true)
 |-- PRES: string (nullable = true)
 |-- TEMP: string (nullable = true)
 |-- cbwd: string (nullable = true)
 |-- Iws: string (nullable = true)
 |-- precipitation: string (nullable = true)
 |-- Iprec: string (nullable = true)

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值