内容简介:用scala语言,利用spark算子及sparksql来对特定数据进行处理
用到的东西:IDEA、Spark、scala、python
该文章为期末作业,仅供参考
一、数据源
对特定数据分析的前提是有满足条件的数据集,但是一般很难找到符合符合自己需求的数据集,这个时候可以选择自己模拟生成一些随机的数据,毕竟此次只为作业,对数据集的要求并不严格。
一、1.利用python随机生成数据
import random
import string
import pandas as pd
from datetime import datetime, timedelta
# 生成随机产品型号
def generate_product_model():
return random.choice(['L100', 'L200', 'L300', 'L400'])
# 生成指定时间格式的随机日期
def generate_specific_random_date(start_date, num_rows):
current_date = start_date.replace(hour=8, minute=30, second=0, microsecond=0)
date_list = [current_date]
for _ in range(num_rows - 1):
current_date += timedelta(minutes=0.5)
date_list.append(current_date)
return date_list
# 生成随机产品生产批次
def generate_production_batch(length=5):
return ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(length))
# 生成随机产品生产数量
def generate_production_quantity():
return random.randint(1, 1000)
# 生成是否测试生产
def generate_testing_status(quantity):
return quantity < 50
# 生成次品生产数
def generate_defective_quantity():
if random.random() < 0.9:
return []
else:
return [random.randint(1, 10) for _ in range(random.randint(1, 5))]
# 生成几号流水线
def generate_pipeline_number():
return random.choice(['K1', 'K2', 'K3','K4','K5','K6'])
# 控制生成行数
num_rows = 1441
# 生成数据
start_date = datetime(2023, 11, 14)
random_dates = generate_specific_random_date(start_date, num_rows)
data = {
#流水线编号
'assemblyLine_number': [generate_pipeline_number() for _ in range(num_rows)],
#产品型号
'productNumber': [generate_product_model() for _ in range(num_rows)],
#生产批次
'ProductionLot' : [generate_production_batch() for _ in range(num_rows)],
#生产日期
'productionDate': [date.strftime('%Y-%m-%d %H:%M:%S') for date in random_dates],
#生产数量
'productionQuantity': [generate_production_quantity() for _ in range(num_rows)],
#次品生产数量
'defectiveProductionQuantity' : [generate_defective_quantity() for _ in range(num_rows)]
}
# 创建表格对象
df = pd.DataFrame(data)
df['testProduction'] = [generate_testing_status(qty) for qty in data['productionQuantity']]
df
这里展示的是利用python来随机生成数据并保存为表格对象的源码,图里利用到了python的一些库,并封装成函数方便表格对象创建时候的调用。
生成数据如下:
一、2.将python的表格对象保存为本地json文件
因为spark读取json的特殊性,json文件格式必须为行存储,即一行为一条json格式的数据,没有换行符。所以必须在保存的时候就做好换行处理。其实不用换行处理用逗号隔开也是可以的,但是后期就要花更多的功夫去兼容。
这里介绍一下python的一个三方库jsonlines,它可以很好把一个表格对象直接转成行存储的json文件。jsonlines参考使用来自这里
之后我们在python里使用jsonlines将我们的表格对象转为json格式的文件。
import jsonlines
with jsonlines.open('2023-11-14.data.json', mode='w') as writer:
for i in range(df.index.stop):
json_data = dict(df.iloc[i])
json_data["productionQuantity"] = int(json_data["productionQuantity"])
json_data["testProduction"] = bool(json_data["testProduction"])
writer.write(json_data)
首先循环提取表格对象的每一行数据并打包成字典然后写入json文件,不会存在换行符。这里的表格对象也可以直接使用上述数据生成代码里的data,即生成表格对象的原始字典。这一步需要注意的是,jsonlines无法转换数据中包含numpy数据类型的对象,如果你的数据对象里的整数是numpy.int64类型的,那么他会报错。
二、利用scala对数据进行分析
二、1.sparksql
根据需求对数据进行分析,我自己写了一个指标说明文档,这里就不列出。直接展示代码,这里展示了用sparksql来对数据进行一个聚合。
package com.dzk.Job
import org.apache.spark.sql.functions.desc
import org.apache.spark.sql.{DataFrame, SparkSession}
object a_assemblyLine_number_productionQuantity {
def main(args: Array[String]): Unit = {
val ss: SparkSession = new SparkSession.Builder().appName("demo").master("local").getOrCreate()
// val df: DataFrame = ss.read.json("hdfs://20210322005-master:9000/2023-11-14.data.json")
val df: DataFrame = ss.read.json("2023-11-14.data.json")
df.groupBy("assemblyLine_number")
.sum("productionQuantity")
.withColumnRenamed("sum(productionQuantity)","流水线sum")
.orderBy(desc("流水线sum"))
.show()
}//main
}//object
这里简单的写了一个sparksql来完成我的需求,他将某两列进行一个聚合,为我展示出各个流水线生产出的总产品数量
二、2.sparkRDD
下面还利用RDD的算子来对数据进行一个更复杂的运算,这是sql做不到的。
需求:计算某流水线的交货数,交货数=生产总数-次品书(数组形式存储数值,计算总和得计算该数组元素总和)-样品数(生产数小于50的为测试生产,即样品)
package com.dzk.Job
import com.google.gson.Gson
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.rdd.RDD
object c_assemblyLine_number_defectiveProductionQuantity {
def main(args: Array[String]): Unit = {
val conf: SparkConf = new SparkConf().setAppName("demo").setMaster("local")
val sc: SparkContext = new SparkContext(conf)
// val rdd: RDD[String] = sc.textFile("hdfs://20210322005-master:9000/2023-11-14.data.json")
val rdd: RDD[String] = sc.textFile("2023-11-14.data.json")
rdd.map(
data => {
val value: getClass = new Gson().fromJson(data, classOf[getClass])
value
}
)
.groupBy(x => x.assemblyLine_number)
.map(x=>{
var total = 0
for( one <- x._2 ){
total = total+one.defectiveProductionQuantity.sum
}
(x._1,total);
})
.sortBy(x => x,ascending = false)
.collect()
.foreach(x => println(x))
}//main
}
还有几个指标就不一一说明,该次任务只用到了sparksql以及sparkRDD来对数据进行处理。
三、总结
使用IDE
IDEA、VSCODE
使用语言
scala、python
过程感受
通过这次业务,你可以简要了解一个数据分析的业务的步骤,比如数据获取,数据处理,数据分析,还有指标说明文档,字段说明文档,以及模拟生成数据如何贴近现实。了解s如何利用python生成随机数据,如何将数据保存为行存储的json文件,scala以及sparksql的简单用法。
python按行写入json文件,每一行都是一个标准json对象,但是整体文件却非json对象:https://blog.youkuaiyun.com/Together_CZ/article/details/130963028