Spark 练习之疫情分析

Spark SQL 练习之疫情分析

2020 年,春节假期期间,国内因疫情事件影响巨大!

众志成城,抗击疫情!(衷心希望,形势能够好转)

现在,将使用的 Spark SQL 的功能,分析一组数据!

假设疫情数据有:

  1. 人员信息 (civic_info.csv)
  2. 票务信息(ticket_info.csv)

分析任务如下:

任务序号 任务描述
1 湖北籍人员信息
2 武汉疫区人员信息
3 需要对员工进行隔离观察14天的公司
4 有感染风险的车厢
5 需要隔离观察的人员信息

坚定信心、同舟共济、科学防治、精准施策!坚决打赢疫情防控阻击战!

数据信息(虚拟的测试数据)

civic_info.csv 文件内容

id_no,name,sex,age,province,city,district,residence,home_domicile,working_company
310228198706300137,李言,男,33,湖北,武汉,江岸区,湖北省武汉市江岸区XXX小区NNN室,上海市松江区XXX小区MMM室,XXX有限公司
310228198808241049,朱艳,女,32,湖北,武汉,江汉区,湖北省武汉市江汉区XXX小区NNN室,上海市嘉定区XXX小区MMM室,YYY有限公司
310228198907141175,肖人风,男,31,湖北,武汉,汉阳区,湖北省武汉市汉阳区XXX小区NNN室,上海市浦东新区XXX小区MMM室,ZZZ有限公司
310228199009212154,黄军,男,30,湖北,武汉,青山区,湖北省武汉市青山区XXX小区NNN室,上海市黄浦区XXX小区MMM室,TTT有限公司
310228199101304567,周子明,男,29,湖北,武汉,洪山区,湖北省武汉市洪山区XXX小区NNN室,上海市闵行区XXX小区MMM室,FFF有限公司
310228199204213278,张燕,女,28,湖北,武汉,江夏区,湖北省武汉市江夏区XXX小区NNN室,上海市静安区XXX小区MMM室,SSS有限公司
310228199305213306,江大仁,男,27,湖北,武汉,蔡甸区,湖北省武汉市蔡甸区XXX小区NNN室,上海市长宁区XXX小区MMM室,UUU有限公司
310228199411010721,袁天罡,男,26,湖北,武汉,黄陂区,湖北省武汉市黄陂区XXX小区NNN室,上海市虹口区XXX小区MMM室,III有限公司
310228199503220823,马鹏,男,25,湖北,武汉,硚口区,湖北省武汉市硚口区XXX小区NNN室,上海市徐汇区XXX小区MMM室,PPP有限公司
310228199608120317,聂平,男,24,湖北,黄冈,黄州区,湖北省黄冈市黄州区XXX小区NNN室,湖北省武汉市东西湖区XXX小区MMM室,WWW有限公司
310228199609170831,胡冰,女,24,湖北,孝感,孝南区,湖北省孝感市孝南区XXX小区NNN室,湖北省武汉市江夏区XXX小区MMM室,QQQ有限公司

ticket_info.csv 文件内容

ticket_no,train_no,carriage_no,seat_no,passenger_name,passenger_id,departure,destination,departure_time,arrival_time
HB9567,SH6634,B,11,李言,310228198706300137,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HA6749,SH6634,C,23,朱艳,310228198808241049,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HC7746,SH6634,D,14,肖人风,310228198907141175,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HD8279,SH6634,A,22,黄军,310228199009212154,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HM3324,SH6634,C,12,周子明,310228199101304567,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HB4597,SH6634,D,23,张燕,310228199204213278,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HA2163,SH6634,E,07,江大仁,310228199305213306,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HC5632,SH6634,A,03,袁天罡,310228199411010721,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HB3306,SH6634,B,09,马鹏,310228199503220823,武汉,上海,2020-02-09|19:30,2020-02-10|10:30
HA1601,SH6634,C,11,梁冬,310228199307290931,重庆,上海,2020-02-09|15:30,2020-02-10|10:30
HA2703,SH6634,D,15,赵珂,310228199106151321,四川,上海,2020-02-09|12:30,2020-02-10|10:30
HC7734,SH6634,F,13,戴拿,310228199212012371,拉萨,上海,2020-02-09|06:30,2020-02-10|10:30

分析数据

首先,测试要用的数据是很规整的,就不进行数据清洗了。(反正是用的 Spark SQL 进行处理的,查询效率暂时不做考究!)

使用 Spark SQL 中的 DataFrame 创建一个临时视图,然后使用临时视图调用 sql 方法。

重点是设计 sql 语句!

代码实现

项目目录结构

在这里插入图片描述

设计简介

首先,套用了老套的 MVC 结构思想,将项目设计为数据访问层,以及设计了单例对象 SparkUtil ,用这个单例对象去初始化 SparkSession。然后是接口设计(原谅我是一个 java 程序员吧,可以这麽理解哈,其实是 trait 的设计),首先是一个 BaseDao,它的职能是将实例化后的单例对象 sparkUtil 设置到实现类中去。

接着是业务方面,两个基本的接口,定义了需要完成的任务,也就是 DocumentContentDaoPersonnelInformationDao 。然后是它们对应的实现类,最终,需要一个入口方法!也就是 EpidemicDemo 类。

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.feng</groupId>
    <artifactId>spark_demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spark.version>2.4.4</spark.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.spark</groupId>
            <artifactId>spark-sql_2.11</artifactId>
            <version>${spark.version}</version>
        </dependency>
    </dependencies>
</project>

resources 中的两个 csv 文件

文件内容,上文中已经给出!

SparkUtil.scala 文件

package org.feng.util

import org.apache.spark.sql.{DataFrame, SparkSession}

/**
  * Created by Feng on 2020/2/9 13:45
  * CurrentProject's name is spark_demo
  * Spark 读取 csv 文件的工具类:设计为单例。
  *
  * @see org.feng.dao.BaseDao
  */
class SparkUtil {

  val spark = SparkSession
    .builder()
    .appName("SparkUtil_".concat(System.currentTimeMillis().toString))
    .master("local")
    .getOrCreate()


  def getDF(path:String): DataFrame ={
    // 加载 csv 文件
    spark.read.format("csv")
      .option("sep", ",")
      .option("inferSchema", "true")
      .option("header", "true")
      .load(path)
  }
}

BaseDao.scala

package org.feng.dao

import org.feng.util.SparkUtil

/**
  * Created by Feng on 2020/2/9 14:03
  * CurrentProject's name is spark_demo
  *
  */
trait BaseDao {
  /**
    * 使用前:必须先 set 一个值
    * new 一个全局的 SparkUtil 对象
    */
  var sparkUtil:SparkUtil = _

  def setSparkUtil(_sparkUtil:SparkUtil):Unit ={
    sparkUtil = _sparkUtil
  }

  def getSparkUtil:SparkUtil={
    sparkUtil
  }
}

PersonnelInformationDao.scala

package org.feng.dao


/**
  * Created by Feng on 2020/2/9 13:27
  * CurrentProject's name is spark_demo
  * 读取人员信息 civic_info.csv 文件
  */
trait PersonnelInformationDao extends BaseDao {
  /**
    * 查询湖北籍人员信息
    */
  def hubeiPersonnel():Unit

  /**
    * 查询武汉疫区人员
    */
  def wuhanPersonnel():Unit

  /**
    * 需要对员工隔离 14 天的公司
    */
  def someCompany():Unit
}

DocumentContentDao.scala

package org.feng.dao

/**
  * Created by Feng on 2020/2/9 13:29
  * CurrentProject's name is spark_demo
  *
  * 读取文件内容 ticket_info.csv 文件
  */
trait DocumentContentDao extends BaseDao {
  /**
    * 查询有感染风险的车厢
    */
  def infectedCarriage():Unit

  /**
    * 需要隔离观察的人员信息
    */
  def segregatedObservers():Unit
}

PersonnelInformationDaoImpl.scala

package org.feng.dao.impl

import org.feng.dao.PersonnelInformationDao

/**
  * Created by Feng on 2020/2/9 13:44
  * CurrentProject's name is spark_demo
  */
class PersonnelInformationDaoImpl extends PersonnelInformationDao {

  /**
    * 查询湖北籍人员信息
    */
  override def hubeiPersonnel(): Unit = {
    sparkUtil.spark
      .sql("select id_no,name,province from civic_info where province = '湖北'")
      .show()
  }

  /**
    * 查询武汉疫区人员
    */
  override def wuhanPersonnel(): Unit = {
    sparkUtil.spark
      .sql("select id_no,name,city from civic_info where city = '武汉'")
      .show()
  }

  /**
    * 需要对员工隔离 14 天的公司
    */
  override def someCompany(): Unit = {
    sparkUtil.spark
      .sql("select working_company from civic_info where city = '武汉'")
      .show()
  }
}

DocumentContentDaoImpl.scala

package org.feng.dao.impl

import org.feng.dao.DocumentContentDao

/**
  * Created by Feng on 2020/2/9 15:21
  * CurrentProject's name is spark_demo
  */
class DocumentContentDaoImpl extends DocumentContentDao{
  /**
    * 查询有感染风险的车厢
    */
  override def infectedCarriage(): Unit = {
    sparkUtil.spark
      .sql("select train_no,carriage_no from ticket_info where departure = '武汉'")
      .distinct()
      .show()
  }

  /**
    * 需要隔离观察的人员信息
    */
  override def segregatedObservers(): Unit = {
    sparkUtil.spark
      .sql("select id_no,name from civic_info,ticket_info where civic_info.name = ticket_info.passenger_name and " +
        "departure = '武汉'")
      .show()
  }
}

EpidemicDemo.scala

package org.feng.client

import org.feng.dao.impl.{DocumentContentDaoImpl, PersonnelInformationDaoImpl}
import org.feng.util.SparkUtil

/**
  * Created by Feng on 2020/2/9 13:21
  * CurrentProject's name is spark_demo
  * 疫情分析
  */
object EpidemicDemo {
  def main(args: Array[String]): Unit = {
    // 创建唯一的 sparkUtil
    val sparkUtil = new SparkUtil

    // 创建数据访问层的对象
    val personnelInformationDao = new PersonnelInformationDaoImpl
    val documentContentDao = new DocumentContentDaoImpl
    // 设置唯一的 sparkUtil
    personnelInformationDao.setSparkUtil(sparkUtil)
    documentContentDao.setSparkUtil(sparkUtil)

    // csv 文件路径
    val civicInfoPath= "D:\\jee-2019-7-idea-maven-workspace\\spark_demo\\src\\main\\resources\\civic_info.csv"
    val ticketInfoPath = "D:\\jee-2019-7-idea-maven-workspace\\spark_demo\\src\\main\\resources\\ticket_info.csv"
    // 创建视图
    sparkUtil.getDF(civicInfoPath).createOrReplaceTempView("civic_info")
    sparkUtil.getDF(ticketInfoPath).createOrReplaceTempView("ticket_info")

    // 查询湖北籍人员信息:输出到控制台
    personnelInformationDao.hubeiPersonnel()
    // 查询武汉疫区人员信息:输出到控制台
    personnelInformationDao.wuhanPersonnel()
    // 查询需要对员工隔离 14 天的公司
    personnelInformationDao.someCompany()

    // 查询有感染风险的车厢
    documentContentDao.infectedCarriage()
    // 查询需要隔离观察的人员信息
    documentContentDao.segregatedObservers()
  }
}

程序运行结果

查询湖北籍人员信息

+------------------+------+--------+
|             id_no|  name|province|
+------------------+------+--------+
|310228198706300137|  李言|    湖北|
|310228198808241049|  朱艳|    湖北|
|310228198907141175|肖人风|    湖北|
|310228199009212154|  黄军|    湖北|
|310228199101304567|周子明|    湖北|
|310228199204213278|  张燕|    湖北|
|310228199305213306|江大仁|    湖北|
|310228199411010721|袁天罡|    湖北|
|310228199503220823|  马鹏|    湖北|
|310228199608120317|  聂平|    湖北|
|310228199609170831|  胡冰|    湖北|
+------------------+------+--------+

查询武汉疫区人员信息

+------------------+------+----+
|             id_no|  name|city|
+------------------+------+----+
|310228198706300137|  李言|武汉|
|310228198808241049|  朱艳|武汉|
|310228198907141175|肖人风|武汉|
|310228199009212154|  黄军|武汉|
|310228199101304567|周子明|武汉|
|310228199204213278|  张燕|武汉|
|310228199305213306|江大仁|武汉|
|310228199411010721|袁天罡|武汉|
|310228199503220823|  马鹏|武汉|
+------------------+------+----+

查询需要对员工隔离 14 天的公司

+---------------+
|working_company|
+---------------+
|    XXX有限公司|
|    YYY有限公司|
|    ZZZ有限公司|
|    TTT有限公司|
|    FFF有限公司|
|    SSS有限公司|
|    UUU有限公司|
|    III有限公司|
|    PPP有限公司|
+---------------+

查询有感染风险的车厢

+--------+-----------+
|train_no|carriage_no|
+--------+-----------+
|  SH6634|          C|
|  SH6634|          B|
|  SH6634|          D|
|  SH6634|          A|
|  SH6634|          E|
+--------+-----------+

查询需要隔离观察的人员信息

+------------------+------+
|             id_no|  name|
+------------------+------+
|310228198706300137|  李言|
|310228198808241049|  朱艳|
|310228198907141175|肖人风|
|310228199009212154|  黄军|
|310228199101304567|周子明|
|310228199204213278|  张燕|
|310228199305213306|江大仁|
|310228199411010721|袁天罡|
|310228199503220823|  马鹏|
+------------------+------+

共勉

再声明一次,虽然此次练习题目不难,但是我现在的心情却是很难!

这次疫情,传染性高于03年的非典,而且得病的人数也很多。

但最近两天应该是有了好消息的,就是目前的一个确诊人数的增幅降低了!

这是一个好消息!希望呢,疫情快些过去,大家能安然度过!

另外,刚才还看到一个词语: 别来无恙! 你品,你细品哈!

发布了108 篇原创文章 · 获赞 117 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/FBB360JAVA/article/details/104236497