【大数据开发】SparkCore、SparkSQL综合练习——对农产品数据进行分析

发现一个idea很神奇的功能,每次写一堆算子的时候,先在最后面写一个Action算子过去,然后再从中间开始写transformation算子,这个时候神奇的事情发生了,在每个算子后面会显示出灰色的返回值类型!!!

一、数据背景

该数据每日进行采集汇总。数据范围涵盖全国主要省份(港澳台、西藏、海南暂无数据)的180+的大型农产品批发市场,380+的农产品品类(由于季节性和地域性等特点,每日的数据中不一定会涵盖全部的农产品品类)。

二、数据类型

农产品批发市场价格数据products.txt	
	中文名称			英文名称	数据类型
	农产品名称(1)	name	string
	批发价格(2)		price	float
	采集时间(3)		craw_time	timestamp
	批发市场名称(4)	market	string
	省份(5)			province	string
	城市(6)			city	string

三、功能要求

要求使用分别使用RDD、DataFrame两种方式实现

1、农产品市场个数统计
(省份,蔬菜,1)
1)统计每个省份的农产品市场总数
2)统计没有农产品市场的省份有哪些

2、农产品种类统计
1)根据农产品类型数量,统计排名前 3 名的省份
2)根据农产品类型数量,统计每个省份排名前 3 名的农产品市场

3、价格区间统计,计算山西省每种农产品的价格波动趋势,即计算每天价格均值,并将结果输出到控制台上。
某种农产品的价格均值计算公式:
PAVG = (PM1+PM2+…+PMn-max§-min§)/(N-2)
其中,P 表示价格,Mn 表示 market,即农产品市场。PM1 表示 M1 农产品市场的该产品价格,max§表示价格最大值,min§价格最小值。

四、SparkCore代码实现

4.1 农产品市场个数统计

4.1.1

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

/**
 * 1)统计每个省份的农产品市场总数
 */
object ByRdd_1_1 {

    private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("dataframe"))
    private val productRDD: RDD[String] = sc.textFile("src/file/test/products.txt")
    def main(args: Array[String]): Unit = {
        //1.按照一个或者多个tab键切割(\s匹配任何空白字符,包括空格、制表符、换页符等等)
        val provinceRDD: RDD[(String, String)] = productRDD.filter(_.split("\\s+").length == 6)
            .map(line => {
                val parts: Array[String] = line.split("\\s+")
                (parts(4), parts(3))
            })
        //2.去除重复数据,按照key分组计算
        val result: collection.Map[String, Long] = provinceRDD.distinct()
            .countByKey()

        for ((k, v) <- result) {
            println(s"省份:$k ,数量:$v")
        }
    }
}

4.1.2

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

/**
 * 2)统计没有农产品市场的省份有哪些
 */
object ByRDD_1_2 {
    private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("dataframe"))
    private val productRDD: RDD[String] = sc.textFile("src/file/test/products.txt")
    private val allProvinceRDD: RDD[String] = sc.textFile("src/file/test/allprovinces.txt")

    def main(args: Array[String]): Unit = {
        //1.按照一个或者多个tab键切割(\s匹配任何空白字符,包括空格、制表符、换页符等等)
        val province: RDD[String] = productRDD.filter(_.split("\\s+").length == 6)
            .map(line => line.split("\\s+")(4))

        //2.读取省份信息

        val allProvinces: RDD[String] = allProvinceRDD.map(line => line.split("\\s+")(0))

        //3.求出省份
        val result: RDD[String] = allProvinces.subtract(province)
        result.foreach(println)
    }
}

4.2农产品种类统计

4.2.1

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

/**
 *2、农产品种类统计
 *1)根据农产品类型数量,统计排名前 3 名的省份
 */

object ByRDD_2_1 {

    private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("dataframe"))
    private val productRDD: RDD[String] = sc.textFile("src/file/test/products.txt")

    def main(args: Array[String]): Unit = {

        //1.得到RDD[(省份, 种类)]
        val provinceAndType: RDD[(String, String)] = productRDD.filter(_.split("\\s+").length == 6)
            .map(line => {
                val parts: Array[String] = line.split("\\s+")
                (parts(4), parts(0))
            })

        //2.计算每个省份的种类和
        val sumRDD: RDD[(String, Int)] = provinceAndType.distinct().mapValues(_ => 1).reduceByKey(_ + _)

        sumRDD.sortBy(-_._2)
            .take(3)
            .foreach(println)
    }
}

4.2.2

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

object ByRDD_3_1 {
    private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("dataframe"))
    private val productRDD: RDD[String] = sc.textFile("src/file/test/products.txt")

    def main(args: Array[String]): Unit = {

        //1.获取 RDD[((省份, 市场), 种类)]
        val provinceAndTypeRDD: RDD[((String, String), String)] = productRDD.filter(_.split("\\s+").length == 6)
            .map(line => {
                val parts: Array[String] = line.split("\\s+")
                ((parts(4), parts(3)),parts(0))
            })

        provinceAndTypeRDD.distinct()
            .mapValues(_ => 1)  //这一步可以在1.位置做
            .reduceByKey(_ + _)
            .map(t => (t._1._1, (t._1._2, t._2)))    //重新划分Rdd的类型
            .groupByKey()
            .mapValues(_.toList.sortBy(-_._2).take(3))
            .mapValues(_.map(_._1))     //去除数量,保留省份
            .foreach(println)
    }
}

4.3计算山西省每种农产品的价格波动趋势

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

object ByRDD_3_2 {
    private val sc: SparkContext = new SparkContext(new SparkConf().setMaster("local").setAppName("dataframe"))
    private val productRDD: RDD[String] = sc.textFile("src/file/test/products.txt")

    def main(args: Array[String]): Unit = {
        // RDD[(农产品, 价格)
        val nameAndPriceRDD: RDD[(String, Double)] = productRDD.filter(_.split("\\s+").length == 6)
            .map(line => {
                val productInfo: Array[String] = line.split("\\s+")
                (productInfo(4), productInfo(0), productInfo(1).toDouble)
            })
            .filter(_._1.equals("山西"))
            .map(t => (t._2, t._3))

        nameAndPriceRDD
            .groupByKey()
            .map(t => {
                if (t._2.size>2)
                    (t._1, ((t._2.sum - t._2.max - t._2.min)/t._2.size).formatted("%.2f"))
                else
                    (t._1, (t._2.sum/t._2.size).formatted("%.2f"))
            })       // 农产品分类
            .foreach(println)

    }

}

五、SparkSQL代码实现

import exam03.common._
import org.apache.spark.sql.{DataFrame, Dataset, Row, SparkSession}

/**
 *
 * 1、农产品市场个数统计
 *      1)统计每个省份的农产品市场总数
 *      2)统计没有农产品市场的省份有哪些
 * 2、农产品种类统计
 *      1)根据农产品类型数量,统计排名前 3 名的省份
 *      2)根据农产品类型数量,统计每个省份排名前 3 名的农产品市场
 * 3、价格区间统计,计算山西省每种农产品的价格波动趋势,即计算每天价格均值,并将结果输出到控制台上。
 *
 */
object MainApplication extends App {
    // 1. 获取SparkSession
    private val spark: SparkSession = SparkHelper.getSparkSession
    import spark.implicits._
    import org.apache.spark.sql.functions._
    // 2. 创建DF
    private val productsDF: DataFrame = {
        spark.read.option("delimiter", "\t").csv(Constants.PATH_PRODUCTS)
            .withColumnRenamed("_c0", "name")
            .withColumnRenamed("_c1", "price")
            .withColumnRenamed("_c2", "craw_time")
            .withColumnRenamed("_c3", "market")
            .withColumnRenamed("_c4", "province")
            .withColumnRenamed("_c5", "city")
            .na.drop()  // drop掉null值
    }
    private val provincesDF: DataFrame = {
        spark.read.option("delimiter", "\t").csv(Constants.PATH_PROVINCES)
            .withColumnRenamed("_c0", "province")
            .withColumnRenamed("_c1", "short_hand")
            .na.drop()
    }

    // 3. 题目实现
    // 3.1. 统计每个省份的农产品市场总数
    productsDF.select("market", "province").distinct().groupBy("province").count().show()
    // 3.2. 统计没有农产品市场的省份有哪些
    private val existsProvinceDF: Dataset[Row] = productsDF.select("province", "market").distinct()
    private val allProvinceDF: Dataset[Row] = provincesDF.select("province").distinct()
    existsProvinceDF.join(allProvinceDF, Seq("province"), "right")
        .filter("market is null")
        .drop("market")
        .show()

    // 3.3. 根据农产品类型数量,统计排名前 3 名的省份
    productsDF.select("name", "province")
        .groupBy("province")
        .agg(countDistinct("name").as("count"))
        .orderBy(-'count)
        .limit(3)
        .show()

    // 3.4. 根据农产品类型数量,统计每个省份排名前 3 名的农产品市场
    productsDF.select("name","market","province")
        .groupBy("province","market").count()
        .orderBy($"province",$"count".desc)
        .repartition(provincesDF.count.asInstanceOf[Int],$"province")
        .foreachPartition(it=>{it.take(3).foreach(println)})

    // 3.5. 计算山西省的每种农产品的价格波动趋势,即计算每天价格均值
    productsDF.filter("province='山西'")
        .groupBy("craw_time","name")
        .agg(when(count($"price")>2,((sum($"price")-max($"price")-min($"price"))/(count($"price")-2)))
            .otherwise(sum($"price")/count($"price"))
            .as("pavg"))
        .selectExpr("craw_time","name","cast(pavg as decimal(20,2)) as pavg")
        .show()
}

六、业务数据

products.txt

茄子	3.20	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
西红柿	4.20	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
黄瓜	4.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
冬瓜	2.20	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
白萝卜	1.40	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
胡萝卜	1.60	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
生姜	12.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
豆角	6.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
香蕉	6.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
猪肉	21.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
鸡蛋	8.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
土豆	2.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
菜花	3.20	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
洋白菜	2.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
大蒜	3.80	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
生菜	5.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
西葫芦	3.20	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
西瓜	5.80	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
活鲤鱼	12.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
茴香	4.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
香菇	8.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
菠菜	3.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
小葱	1.40	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
富士苹果	6.00	2018/1/1	河北怀来县就西果菜批发市场有限责任公司	河北	怀来
活草鱼	14.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
活鲫鱼	14.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
黑鱼	20.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
花鲢活鱼	12.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
白鲢活鱼	8.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
野生甲鱼	420.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
人工甲鱼	160.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
江蟹	180.00	2018/1/1	江苏建湖县水产批发市场	江苏	建湖
大白菜	0.70	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
洋白菜	2.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
韭菜	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
芹菜	2.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
菠菜	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
油菜	1.20	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
菜花	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
蒜苔	8.60	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
生菜	5.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
黄瓜	3.40	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
豆角	7.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
长茄子	2.80	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
尖椒	5.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
青椒	4.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
西红柿	3.60	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
良薯	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
红萝卜	1.20	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
白萝卜	1.60	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
冬瓜	1.10	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
南瓜	6.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
莴笋	4.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
西葫芦	3.20	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
葱头	1.40	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
莲藕	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
大葱	3.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
平菇	4.60	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
香菇	7.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
苹果	8.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
香蕉	6.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
西瓜	2.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
巨峰葡萄	8.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
猪肉	21.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
牛肉	48.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
羊肉	46.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
鸡蛋	9.60	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
白条鸡	17.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
活草鱼	14.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
活鲤鱼	10.50	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
白鲢活鱼	16.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
花鲢活鱼	14.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
活鲫鱼	13.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
大带鱼	19.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
大黄花鱼	25.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
粳米	4.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
面粉	2.90	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
菜油	12.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
豆油	10.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
花生油	16.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
香油	30.00	2018/1/1	山西大同振华蔬菜批发市场	山西	大同
大白菜	0.90	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
生菜	2.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
大葱	2.80	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
小葱	3.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
大蒜	4.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
鱼腥草(折耳根)	4.40	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
尖椒	7.60	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
黄瓜	3.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
冬瓜	1.10	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
南瓜	2.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
白萝卜	1.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
胡萝卜	2.60	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
土豆	2.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
生姜	9.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
莲藕	5.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
富士苹果	6.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
香蕉	3.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
猪肉	23.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
洋白菜	1.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
豌豆	5.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
蒜苔	6.80	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
西红柿	4.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
条形辣椒干(小米椒)	22.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
莴笋	1.40	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
菜花	2.60	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
芹菜	3.00	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
青椒	5.40	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
茄子	4.20	2018/1/1	四川西昌广平农副土特产品市场	四川	西昌
大白菜	1.00	2018/1/1	浙江义乌农贸城	浙江	义乌
芹菜	2.60	2018/1/1	浙江义乌农贸城	浙江	义乌
菠菜	3.60	2018/1/1	浙江义乌农贸城	浙江	义乌
大葱	3.20	2018/1/1	浙江义乌农贸城	浙江	义乌

allprovince.txt

河北	HE
山西	SX
辽宁	LN
吉林	JL
黑龙江	HL
江苏	JS
浙江	ZJ
安徽	AH
福建	FJ
江西	JX
山东	SD
河南	HA
湖北	HB
湖南	HN
广东	GD
海南	HI
四川	SC
贵州	GZ
云南	YN
陕西	SN
甘肃	GS
青海	QH
台湾	TW
内蒙古	IM
广西	GX
西藏	XZ
宁夏	NX
新疆	XJ
香港	HK
澳门	MO
天津	TJ
北京	BJ
重庆	CQ
上海	SH
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值