数据清洗

在对数据进行处理的时候,很多时候需要我们进行数据清洗。
下面的案例就是对大量的数据进行处理:
每行代码完成的任务在备注中都有叙述

package etl

import java.io.File
import java.text.SimpleDateFormat
import java.util.Date

import bean.{
   Logs, logSchema}
import config.ConfigHelper
import org.apache.commons.io.FileUtils
import org.apache.spark.rdd.RDD
import org.apache.spark.sql
import org.apache.spark.sql.{
   Row, SaveMode, SparkSession}



/**
 * 1、清洗
 * 2、转换
 * */

object log2Parquet {
   
  def main(args: Array[String]): Unit = {
   
    //会有两个参数,一个是输入路径,一个是输出路径,因此参数<2的话说明有参数丢失,报错提醒我们检查
    if(args.length<2){
   
      println("参数错误")
      return
    }
    //需要创建一个SparkSession
    val session=SparkSession
      //创建
      .builder()
      //设置是否是在本地运行
      //*代表几个线程
      .master("local[*]")
      //设置进程的名称
      .appName(this.getClass.getName)
      //压缩
      .config("spark.sql.parquet.compression.codec",ConfigHelper.parquetCode)
      //序列化
      .config("spark.serializer",ConfigHelper.serializer)
      //获取(如果有就拿原来的,没有就创建)
      .getOrCreate()
    //导入隐式转换
    import session.implicits._
    //读取数据
    val sources: RDD[String] = session.sparkContext.textFile(args(0))
    //切分数据,判断数据长度(字段的数量)是否大于55
    //因为设置了55个字段,如果切割以后字段数量小于55,说明一定在切分过程中出现了问题
    //limit
    //什么都不加:300T//      剪切完:300T
    //加-1:300T//      剪切完:300T “” “” “” “” “” “”
    //filter效率很低,尽量少用
    //rdd复用提高效率:
    //缓存机制:不是安全的,缓存之前的血统关系
    //缓存分为cache和persist
    //cache:底层调用persist,传给内存
    //persist的缓存级别:十二种
    //分为:内存,内存序列化,内存磁盘,内存磁盘序列化,磁盘,堆外内存 X2
    // 检查点机制:将中间的数据,存到一个可靠的文件系统里,比如HDFS(数据是安全的,会切断之前的血统关系)
    //spilt中的regax属性里面的"\\"是转译符号,除非后面的符号是","或者";",不然类似于"|"这样的前面都要加上"\\"
    val filted = sources.map(line=>line.split("\\|",line.length)).filter(_.length>=55)
    //挨个处理300T和300TATO
    //获取当前时间和数据时间
    val format = new SimpleDateFormat("yyyyMMddHHmmss")
    val date = new Date()
    val currentTime: Long = date.getTime
    //清洗300T和300TATO
    //四道筛选都满足的数据才能留下来
    //第一道筛选:第一个属性不包含300T和300TATO的数据剔除
    val rdd300T = filted.filter(arr=> arr(0).contains("300T") || arr(0).contains("300TATO"))
      //第二道筛选:剔除第18个属性里包含复位、SB待机和常用制动报警的数据
      .filter(arr => !arr(17).contains("复位") || !arr(17).contains("SB待机") || !arr(17).contains("常用制动报警"))
      //第三道筛选:第八个属性是入库时间与数据时间相差的时间,超过一定时间的数据剔除
      //currentTime:现在的时间
      //(format.parse(arr(7))).getTime:arr(7)是数据入库时间,经过format.parse(),转换成我们之前设定的时间格式,最后加上.getTime就和currentTime的格式一样了,是以毫秒为单位的
      //5 * 365 * 24 * 60 * 60 * 1000:5年
      //5:5年
      //365:一年有365天
      //24:一天有24小时
      //60:一小时有60分钟
      //60:一分钟有60秒
      //1000:因为时间最后的单位是毫秒,而秒和毫秒的进制是1000,所以最后乘上1000
      .filter(arr => (currentTime - format.parse(arr(7)).getTime < 5 * 365 * 24 * 60 * 60 * 1000))
      //第四道筛选:剔除第18个属性里面包含休眠、未知、无致命错误、一致性消息错误、NVMEN故障的数据
      .filter(arr => !arr(17).contains("休眠") || !arr(17).contains("未知") || !arr(17).contains("无致命错误")
        || !arr(17).contains("一致性消息错误") || !arr(17).contains("NVMEN故障"))
    //挑出来当前ATP系统处于故障中
    //distinct:去重
    val rdd300TSF = rdd300T.filter(arr=>arr(17).contains("前ATP系统处于故障中"))
      .map(arr=>{
   
          arr(0)+"|"+
          arr(1)+"|"+
          arr(2)+"|"+
          arr(3)+"|"+
          arr(4)+"|"+
          arr(5)+"|"+
          arr(6)+"|"+
          //arr(7):20150109102323
          
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值