sparkcore-sparksql数据清洗

本文详细介绍了使用Spark Core和Spark SQL进行数据清洗的过程,包括数据格式转换、去除空值、数据结构优化等步骤。通过行转列、列转行操作减少数据冗余,并在Hive中存储和操作数据。最后,利用sqoop将处理后的数据导入到MySQL数据库中,确保表结构的一致性。
摘要由CSDN通过智能技术生成

数据格式

原格式

日期 时间 种类 监测站1数据 监测站…数据
String Int String Double Double

数据清洗

PM2.5表、O3表…

时间 监测站 数据
String(“yyyy-MM-dd-HH“) String Double

这样会出现大量数据冗余但是去掉了空值,并且以时间和监测站为主键更加容易操作。

源数据表节选:

date hour type 1001A 1002A
20150102 1 AQI 117 85
20150102 1 PM2.5 88 34
20150102 1 PM2.5_24h 48 54

思路

先把第一行的表头提取出来,影响操作数据。

除去第一行表头,获取所有数据,对每行数据进行切分,把type作为RDD的主键,再以date+hour作为key,其余数据作为value拼接成map,map为RDD的值。为了区分map中的key和value,date和hour使用",“链接,多个value使用”-"链接。

既(PM2.5,(20150102,1,88-34))

使用filter只取某一个type的数据,然后去掉key,既(20150102,1,88-34)

对RDD进行行转列,对后排的数据进行切分,切分后格式为(20150102,1,Array[88,34])

然后再进行模式匹配,对切分后的数组进行拆分,既行转列(20150102,1,88),(20150102,1,34)

在表头中取出所有的监测站代码组成一个字符串数组

将每一列的数据和监测站代码一一对应。(20150102,1,1001A,88)

输出至文件中。

这个垃圾数据我日,大体上没有问题,具体的文件中全是报错,一定要把所有情况考虑清楚。

有的文件中最后几行没有任何数据,比如22点以后不进行检测的。这样你如果直接去拉去line(3),就会因为没有数据导致数组溢出。

有的文件表头不全,你明明切出来是1563个监测站,但是第1563个监测站就会报数组溢出,挺离谱的。

有的文件甚至连检测的污染物类型都没有,你一取line(2)数组溢出我是没想到的,日了狗了。

数据结构优化

日期 监测站 0时数据 1时数据 …时数据
String(“yyyy-MM-dd“) String Double Double Double

减少了数据冗余,有效的减少存储量。因为一天一共就24个小时,合并成列也不算多。源数据两千八百多个列就挺尼玛离谱。

这样需要先进行行转列,把表头的监测站代码放进数据中,再列转行,把时间调整到表头,比较麻烦,但是既解决了空值问题,又减少了数据冗余。

既然第一步已经将数据格式化了,就可以存入hive进行操作了。

数据上传

先使用rz命令将数据上传到集群中,再上传至hdfs

hadoop fs -put air2015-2018/ /air/input

数据操作

package com.digitalchina

import java.io.IOException
import org.apache.spark.rdd.RDD
import org.apache.spark.{
   SparkConf, SparkContext}

object AirQualityTest {
   
  def main(args: Array[String]): Unit = {
   
    val sparkConf = new SparkConf()
      .setAppName("AirQuality")
    val sc = new SparkContext(sparkConf)
      val readRDD = sc.textFile(args(0))
        val airRDD = readRDD.map(
        line => {
   
          //分割字符串
          val lines = line.split(",")
          //先判断到底是否有数据
          if(lines.length>3) {
   
            //以日期,时间为key
            val key = lines(0) + "," + lines(1)
            //剩下的所有数据为value,循环组成一个map
            var value = lines(3)
            for (i <- 4 to lines.length - 1) {
   
              value = value + "-" + lines(i)
            }
            //以污染物为主键,map为值组成RDD
            (lines(2), (key, value))
          }else{
   
            //如果没有数据,就直接给三个空字符串,后面会去掉空字符串,键值不要给污染物类型line(2)
            //有的数据没有污染物的类型,尼玛离谱line(2)报了个数组溢出,表结构都没有为什么不丢弃啊?
            ("", ("", ""))
          }
        })
      collectRDD(airRDD,"PM2.5",a
  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值