图解大数据 | 综合案例-使用Spark分析挖掘零售交易数据

图解大数据技术:从入门到精通系列教程 本篇内容是ShowMeAI组织的「图解大数据处理与开发」系列教程入口,本教程以大数据技术为根基,给大家讲解大数据开发与数据处理分析的相关知识与技能,并配以相关的实战案例帮助大家学习理解。... 阅读详情
AI摘要

本文介绍了如何使用Python的pyspark处理HDFS上的电商交易数据,完成数据预处理、深入分析(如客户国别销量、销售额、退货情况等),并通过Echarts进行可视化呈现。

作者:韩信子@ShowMeAI
教程地址:http://www.showmeai.tech/tutorials/84
本文地址:http://www.showmeai.tech/article-detail/177
声明:版权所有,转载请联系平台与作者并注明出处

收藏ShowMeAI查看更多精彩内容


引言

电商与新零售是目前大数据与AI应用最广泛的场景之一,本案例以跨国在线零售业务为背景,讲解使用pyspark对HDFS存储的数据进行交易数据分析的过程,并且对分析结果使用echarts做了可视化呈现。

1.环境搭建

本次作业使用的环境和软件如下:

  • (1)Linux操作系统:Ubuntu 16.04
  • (2)Python:3.8
  • (3)Hadoop:3.1.3
  • (4)Spark:2.4.0
  • (5)Bottle:v0.13

Bottle是一个快速、简洁、轻量级的基于WSIG的微型Web框架,此框架除了Python的标准库外,不依赖任何其他模块。安装方法是,打开Linux终端,执行如下命令:

sudo apt-get install python3-pip
pip3 install bottle

2.数据预处理

本案例的数据集来自Kaggle平台,是跨国在线零售业务交易数据,大家可以通过如下的百度网盘地址下载。

数据集和源代码下载(百度网盘)
链接:https://pan.baidu.com/s/1zg2MoNNZrjGTQC5ohwQkJA
提取码:show

这是一家在英国注册的公司,主要销售礼品。数据集 E_Commerce_Data.csv 包含541909条记录,时间跨度为2010-12-01到2011-12-09,每个记录由8个属性组成,具体的含义如下表所示:

字段名称类型含义举例
InvoiceNostring订单编号(退货订单以C开头)536365
StockCodestring产品代码85123A
Descriptionstring产品描述WHITE METAL LANTERN
Quantityinteger购买数量(负数表示退货)6
InvoiceDatestring订单日期和时间12/1/2010 8:26
UnitPricedouble单价(英镑)3.39
CustomerIDinteger客户编号17850
Countrystring国家名称United Kingdom

我们先将数据集E_Commerce_Data.csv上传至hdfs上,命令如下:

hdfs dfs -put E_Commerce_Data.csv

大家可以通过如下命令进入pyspark的交互式编程环境,或者在配置好pyspark的jupyter Notebook中,对数据进行初步探索和清洗:

cd /usr/local/spark #进入Spark安装目录
./bin/pyspark

(1)读取在HDFS上的文件,以csv的格式读取,得到DataFrame对象

df=spark.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load('E_Commerce_Data.csv')

(2)查看数据集的大小,输出541909,不包含标题行

df.count()

(3)打印数据集的schema,查看字段及其类型信息。输出内容就是上文中的属性表

df.printSchema()

(4)创建临时视图data

df.createOrReplaceTempView("data")

(5)由于顾客编号CustomID和商品描述 Description 均存在部分缺失,所以进行数据清洗,过滤掉有缺失值的记录。特别地,由于 CustomID为integer 类型,所以该字段若为空,则在读取时被解析为0,故用 df[“CustomerID”]!=0 条件过滤。

clean=df.filter(df["CustomerID"]!=0).filter(df["Description"]!="")

(6)查看清洗后的数据集的大小,输出406829。

clean.count()

(7)将清洗后的文件以csv的格式,写入 E_Commerce_Data_Clean.csv 中(实际上这是目录名,真正的文件在该目录下,文件名类似于 part-00000,需要确保HDFS中不存在这个目录,否则写入时会报“already exists”错误)

clean.write.format("com.databricks.spark.csv").options(header='true',inferschema='true').save('E_Commerce_Data_Clean.csv')

3.数据分析

数据集和源代码下载(百度网盘)
链接:https://pan.baidu.com/s/1zg2MoNNZrjGTQC5ohwQkJA
提取码:show

我们构建一个总体的分析脚本 sales_data_analysis.py ,先导入需要用到的python模块。

# -*- coding: utf-8 -*-
from pyspark import SparkContext
from pyspark.sql import SparkSession
from pyspark.sql.types import StringType, DoubleType, IntegerType, StructField, StructType
import json
import os

接着初始化SparkSession对象。

sc = SparkContext('local', 'spark_project')
sc.setLogLevel('WARN')
spark = SparkSession.builder.getOrCreate()

之后从HDFS中以csv的格式读取清洗后的数据目录 E_Commerce_Data_Clean.csv ,spark得到DataFrame对象,并创建临时视图data用于后续分析。

df = spark.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load('E_Commerce_Data_Clean.csv')
df.createOrReplaceTempView("data")

为方便统计结果的可视化,将结果导出为json文件供web页面渲染。使用save方法导出数据:

def save(path, data):
    with open(path, 'w') as f:
        f.write(data)

1)数据概览

(1)客户数最多的10个国家

每个客户由编号 CustomerID 唯一标识,所以客户的数量为 COUNT(DISTINCT CustomerID) ,再按照国家 Country 分组统计,根据客户数降序排序,筛选出10个客户数最多的国家。得到的countryCustomerDF为DataFrame 类型,执行 collect() 方法即可将结果以数组的格式返回。

def countryCustomer():
    countryCustomerDF = spark.sql("SELECT Country,COUNT(DISTINCT CustomerID) AS countOfCustomer FROM data GROUP BY Country ORDER BY countOfCustomer DESC LIMIT 10")
    return countryCustomerDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[国家名称,客户数]

(2)销量最高的10个国家

Quantity字段表示销量,因为退货的记录中此字段为负数,所以使用 SUM(Quantity) 即可统计出总销量,即使有退货的情况。再按照国家 Country 分组统计,根据销量降序排序,筛选出10个销量最高的国家。得到的 countryQuantityDF 为DataFrame类型,执行 collect() 方法即可将结果以数组的格式返回。

def countryQuantity():
    countryQuantityDF = spark.sql("SELECT Country,SUM(Quantity) AS sumOfQuantity FROM data GROUP BY Country ORDER BY sumOfQuantity DESC LIMIT 10")
    return countryQuantityDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[国家名称,销量]

(3)各个国家的总销售额分布情况

UnitPrice 字段表示单价,Quantity 字段表示销量,退货的记录中 Quantity 字段为负数,所以使用 SUM(UnitPrice*Quantity) 即可统计出总销售额,即使有退货的情况。再按照国家 Country 分组统计,计算出各个国家的总销售额。得到的 countrySumOfPriceDF 为 DataFrame 类型,执行 collect() 方法即可将结果以数组的格式返回。

def countrySumOfPrice():
    countrySumOfPriceDF = spark.sql("SELECT Country,SUM(UnitPrice*Quantity) AS sumOfPrice FROM data GROUP BY Country")
    return countrySumOfPriceDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[国家名称,总销售额]

(4)销量最高的10个商品

Quantity 字段表示销量,退货的记录中 Quantity 字段为负数,所以使用 SUM(Quantity) 即可统计出总销量,即使有退货的情况。再按照商品编码 StockCode 分组统计,计算出各个商品的销量。得到的 stockQuantityDF 为 DataFrame 类型,执行 collect() 方法即可将结果以数组的格式返回。

def stockQuantity():
    stockQuantityDF = spark.sql("SELECT StockCode,SUM(Quantity) AS sumOfQuantity FROM data GROUP BY StockCode ORDER BY sumOfQuantity DESC LIMIT 10")
    return stockQuantityDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[商品编号,销量]

(5)商品描述的热门关键词Top300

Description字段表示商品描述,由若干个单词组成,使用 LOWER(Description) 将单词统一转换为小写。此时的结果为 DataFrame 类型,转化为 rdd 后进行词频统计,再根据单词出现的次数进行降序排序,流程图如下:

使用Spark分析挖掘零售交易数据; 商品描述的热门关键词Top300; 11-1

得到的结果为RDD类型,为其制作表头 wordCountSchema,包含 word 和 count 属性,分别为 string 类型和 integer 类型。调用 createDataFrame() 方法将其转换为 DataFrame 类型的 wordCountDF,将word为空字符串的记录剔除掉,调用 take() 方法得到出现次数最多的300个关键 词,以数组的格式返回。

def wordCount():
    wordCount = spark.sql("SELECT LOWER(Description) as description from data").rdd.flatMap(lambda line:line['description'].split(" ")).map(lambda word:(word,1)).reduceByKey(lambda a,b:a+b).repartition(1).sortBy(lambda x:x[1],False)

    wordCountSchema = StructType([StructField("word", StringType(), True),StructField("count", IntegerType(), True)])
    wordCountDF = spark.createDataFrame(wordCount, wordCountSchema)
    wordCountDF = wordCountDF.filter(wordCountDF["word"]!='')
    return wordCountDF.take(300)

最后调用save方法就可以将结果导出至文件了,格式如下:

[关键词,次数]

(6)退货订单数最多的10个国家

InvoiceNo 字段表示订单编号,所以订单总数为 COUNT(DISTINCT InvoiceNo),由于退货订单的编号的首个字母为C,例如C540250,所以利用 WHERE InvoiceNo LIKE ‘C%’ 子句即可筛选出退货的订单,再按照国家Country分组统计,根据退货订单数降序排序,筛选出10个退货订单数最多的国家。得到的 countryReturnInvoiceDF 为 DataFrame 类型,执行 collect() 方法即可将结果以数组的格式返回。

def countryReturnInvoice():
    countryReturnInvoiceDF = spark.sql("SELECT Country,COUNT(DISTINCT InvoiceNo) AS countOfReturnInvoice FROM data WHERE InvoiceNo LIKE 'C%' GROUP BY Country ORDER BY countOfReturnInvoice DESC LIMIT 10")
    return countryReturnInvoiceDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[国家名称,退货订单数]

2)关联分析

(7)月销售额随时间的变化趋势

统计月销售额需要3个字段的信息,分别为订单日期 InvoiceDate,销量Quantity和单价UnitPrice。由于InvoiceDate字段格式不容易处理,例如“8/5/2011 16:19”,所以需要对这个字段进行格式化操作。由于统计不涉及小时和分钟数,所以只截取年月日部分,并且当数值小于10时补前置0来统一格式,期望得到年、月、日3个独立字段。先实现 formatData() 方法,利用 rdd 对日期、销量和单价字段进行处理。

def formatData():
    tradeRDD = df.select("InvoiceDate","Quantity","UnitPrice",).rdd
    result1 = tradeRDD.map(lambda line: (line['InvoiceDate'].split(" ")[0], line['Quantity'] , line['UnitPrice']))
    result2 = result1.map(lambda line: (line[0].split("/"), line[1], line[2]))
    result3 = result2.map(lambda line: (line[0][2], line[0][0] if len(line[0][0])==2 else "0"+line[0][0], line[0][1] if len(line[0][1])==2 else "0"+line[0][1], line[1], line[2]))
    return result3

流程图如下:

使用Spark分析挖掘零售交易数据; 月销售额随时间的变化趋势; 11-2

由于要统计的是月销售额的变化趋势,所以只需将日期转换为“2011-08”这样的格式即可。而销售额表示为单价乘以销量,需要注意的是,退货时的销量为负数,所以对结果求和可以表示销售额。RDD的转换流程如下:

使用Spark分析挖掘零售交易数据; 销售额随时间的变化趋势; 11-3

得到的结果为RDD类型,为其制作表头 schema,包含 date 和 tradePrice 属性,分别为string类型和double类型。调用 createDataFrame() 方法将其转换为DataFrame类型的 tradePriceDF ,调用 collect() 方法将结果以数组的格式返回。

def tradePrice():
    result3 = formatData()
    result4 = result3.map(lambda line:(line[0]+"-"+line[1],line[3]*line[4]))
    result5 = result4.reduceByKey(lambda a,b:a+b).sortByKey()
    schema = StructType([StructField("date", StringType(), True),StructField("tradePrice", DoubleType(), True)])
    tradePriceDF = spark.createDataFrame(result5, schema)
    return tradePriceDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[日期,销售额]

(8)日销量随时间的变化趋势

由于要统计的是日销量的变化趋势,所以只需将日期转换为“2011-08-05”这样的格式即可。先调用上例的 formatData() 方法对日期格式进行格式化。RDD的转换流程如下:

使用Spark分析挖掘零售交易数据; 日销量随时间的变化趋势; 11-4

得到的结果为RDD类型,为其制作表头schema,包含date和saleQuantity属性,分别为string类型和integer类型。调用createDataFrame()方法将其转换为DataFrame类型的saleQuantityDF,调用collect() 方法将结果以数组的格式返回。

def saleQuantity():
    result3 = formatData()
    result4 = result3.map(lambda line:(line[0]+"-"+line[1]+"-"+line[2],line[3]))
    result5 = result4.reduceByKey(lambda a,b:a+b).sortByKey()
    schema = StructType([StructField("date", StringType(), True),StructField("saleQuantity", IntegerType(), True)])
    saleQuantityDF = spark.createDataFrame(result5, schema)
    return saleQuantityDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[日期,销量]

(9)各国的购买订单量和退货订单量的关系

InvoiceNo 字段表示订单编号,退货订单的编号的首个字母为C,例如C540250。利用 COUNT(DISTINCT InvoiceNo) 子句统计订单总量,再分别用 WHERE InvoiceNo LIKE ‘C%’ 和 WHERE InvoiceNo NOT LIKE ‘C%’ 统计出退货订单量和购买订单量。接着按照国家 Country 分组统计,得到的returnDF和buyDF均为DataFrame类型,分别表示退货订单和购买订单,如下所示:

使用Spark分析挖掘零售交易数据; 各国的购买订单量和退货订单量的关系; 11-5

再对这两个DataFrame执行join操作,连接条件为国家Country相同,得到一个DataFrame。但是这个DataFrame中有4个属性,包含2个重复的国家Country属性和1个退货订单量和1个购买订单量,为减少冗余,对结果筛选3个字段形成buyReturnDF。如下所示:

使用Spark分析挖掘零售交易数据; 各国的购买订单量和退货订单量的关系; 11-6

最后执行collect()方法即可将结果以数组的格式返回。

def buyReturn():
    returnDF = spark.sql("SELECT Country AS Country,COUNT(DISTINCT InvoiceNo) AS countOfReturn FROM data WHERE InvoiceNo LIKE 'C%' GROUP BY Country")
    buyDF = spark.sql("SELECT Country AS Country2,COUNT(DISTINCT InvoiceNo) AS countOfBuy FROM data WHERE InvoiceNo NOT LIKE 'C%' GROUP BY Country2")
    buyReturnDF = returnDF.join(buyDF, returnDF["Country"] == buyDF["Country2"], "left_outer")
    buyReturnDF = buyReturnDF.select(buyReturnDF["Country"],buyReturnDF["countOfBuy"],buyReturnDF["countOfReturn"])
    return buyReturnDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[国家名称,购买订单数,退货订单数]

(10)商品的平均单价与销量的关系

由于商品的单价UnitPrice是不断变化的,所以使用平均单价AVG(DISTINCT UnitPrice)来衡量一个商品。再利用SUM(Quantity)计算出销量,将结果按照商品的编号进行分组统计,执行collect()方法即可将结果以数组的格式返回。

def unitPriceSales():
    unitPriceSalesDF = spark.sql("SELECT StockCode,AVG(DISTINCT UnitPrice) AS avgUnitPrice,SUM(Quantity) AS sumOfQuantity FROM data GROUP BY StockCode")
    return unitPriceSalesDF.collect()

最后调用save方法就可以将结果导出至文件了,格式如下:

[商品编号,平均单价,销量]

3)小结

在sales_data_analysis.py中添加main函数,将上面的分析过程整合起来方便进行调用,代码如下:

if __name__ == "__main__":

    base = "static/"
    if not os.path.exists(base):
        os.mkdir(base)

    m = {
        "countryCustomer": {
            "method": countryCustomer,
            "path": "countryCustomer.json"
        },
        "countryQuantity": {
            "method": countryQuantity,
            "path": "countryQuantity.json"
        },
        "countrySumOfPrice": {
            "method": countrySumOfPrice,
            "path": "countrySumOfPrice.json"
        },
        "stockQuantity": {
            "method": stockQuantity,
            "path": "stockQuantity.json"
        },
        "wordCount": {
            "method": wordCount,
            "path": "wordCount.json"
        },
        "countryReturnInvoice": {
            "method": countryReturnInvoice,
            "path": "countryReturnInvoice.json"
        },
        "tradePrice": {
            "method": tradePrice,
            "path": "tradePrice.json"
        },
        "saleQuantity": {
            "method": saleQuantity,
            "path": "saleQuantity.json"
        },
        "buyReturn": {
            "method": buyReturn,
            "path": "buyReturn.json"
        },
        "unitPriceSales": {
            "method": unitPriceSales,
            "path": "unitPriceSales.json"
        }
    }

    for k in m:
        p = m[k]
        f = p["method"]
        save(base + m[k]["path"], json.dumps(f()))
        print ("done -> " + k + " , save to -> " + base + m[k]["path"])

上面的代码将所有的函数整合在变量 m中,通过循环调用上述所有方法并导出json文件到当前路径的static目录下。
最后利用如下指令运行分析程序:

cd /usr/local/spark
./bin/spark-submit sales_data_analysis.py

4.数据可视化

本项目可视化使用百度开源的免费数据展示框架Echarts。Echarts是一个纯Javascript的图表库,可以流畅地运行在PC和移动设备上,兼容当前绝大部分浏览器,底层依赖轻量级的Canvas类库ZRender,提供直观,生动,可交互,可高度个性化定制的数据可视化图表。

编写web.py程序,实现一个简单的web服务器,代码如下:

from bottle import route, run, static_file
import json

@route('/static/<filename>')
def server_static(filename):
    return static_file(filename, root="./static")

@route("/<name:re:.*\.html>")
def server_page(name):
    return static_file(name, root=".")

@route("/")
def index():
    return static_file("index.html", root=".")

run(host="0.0.0.0", port=8888)

bottle服务器对接收到的请求进行路由,规则如下:

(1)访问/static/时,返回静态文件
(2)访问/.html时,返回网页文件
(3)访问/时,返回首页index.html

服务器的8888端口监听来自任意ip的请求(前提是请求方能访问到这台服务器)。

首页index.html的主要代码如下(由于篇幅较大,只截取主要的部分)

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,height=device-height">
    <title>E-Commerce-Data 在线零售业务数据分析</title>
<style>
/* 省略 */
    </style>
</head>

<body>
    <div class="container">
    /* 只展示第一个统计结果的代码,其余省略 */
        <div class="chart-group">
            <h3>(1) 客户数最多的10个国家
            <br>
            <small style="font-size: 72%;">
                ——英国的客户最多,达到3950个,数量远大于其他国家;其次是德国、法国、西班牙等
            </small>
            </h3>
            <iframe src="countryCustomer.html" class="frame" frameborder="0"></iframe>
        </div>
    </div>
    <script>document.body.clientHeight;</script>
</body>
</html>

图表页通过一个iframe嵌入到首页中。以第一个统计结果的网页countryCustomer.html为例,展示主要代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <style>
/* 省略 */
    </style>
</head>

<body>
<div id="chart" style="width:95%;height:95%;"></div>
<script src="static/jquery-3.2.1.min.js"></script>
<script src="static/echarts-4.7.0.min.js"></script>
<script>
    var myChart = echarts.init(document.getElementById('chart'));
    myChart.setOption(
    {
        color: ['#3398DB'],
        tooltip: {
            trigger: 'axis',
            axisPointer: {
                type: 'shadow'
            }
        },
        grid: {
            left: '3%',
            right: '4%',
            bottom: '3%',
            containLabel: true
        },
        xAxis: [
            {
                name: '国家',
                data: [],
                axisTick: {
                    alignWithLabel: true
                },
                axisLabel: {  
                   interval:0,  
                   rotate:40  
                }
            }
        ],
        yAxis: [
            {
                name: '客户数',
            }
        ],
        series: [
            {
                name: '客户数',
                type: 'bar',
                barWidth: '60%',
                data: []
            }
        ]
    });
    myChart.showLoading();
    $.getJSON("/static/countryCustomer.json", data => {
        var names=[];
        var nums=[];

        data = data.map(v => ({
            country: v[0],
            customer: parseInt(v[1]),
        }))

        for(var i=0;i<data.length;i++){
            names.push(data[i].country);
            nums.push(data[i].customer);
        }
        myChart.setOption({
            xAxis: {
                data: names
            },
            series: [{
                data: nums
            }]
        });
        myChart.hideLoading();
    })
</script>
</body>
</html>

代码完成后,在代码所在的根目录下执行以下指令启动web服务器:

python3 web.py

若打印出以下信息则表示web服务启动成功。接着,可以通过使用浏览器访问网页的方式查看统计结果。

Bottle v0.12.18 server starting up (using WSGIRefServer())...
Listening on http://0.0.0.0:9999/
Hit Ctrl-C to quit.

我们可以把整个数据分析和可视化的过程整理成一个处理流水线,编写run.sh脚本:

  • 首先向spark提交sales_data_analysis.py程序对数据进行统计分析,生成的json文件会存入当前路径的static目录下;
  • 接着运行web.py程序,即启动web服务器对分析程序生成的json文件进行解析渲染,方便用户通过浏览器查看统计结果的可视化界面。
#!/bin/bash
cd /usr/local/spark
./bin/spark-submit sales_data_analysis.py
python3 web.py

注意:该脚本的流程要能正常运行,需要保证HDFS中有 E_Commerce_Data_Clean.csv,大家要注意提前把清洗过后的数据存放至HDFS。

5.可视化图示

(1)客户数最多的10个国家

英国的客户最多,达到3950个,数量远大于其他国家;其次是德国、法国、西班牙等。

使用Spark分析挖掘零售交易数据; 客户数最多的10个国家; 11-7

(2)销量最高的10个国家

英国的销量最高,达到4008533件,远大于其他国家;其次是新西兰、爱尔兰、德国等。

使用Spark分析挖掘零售交易数据; 销量最高的10个国家; 11-8

(3)各个国家的总销售额分布情况

英国的总销售额最高,达到6767873.394英镑,占比81.54%

使用Spark分析挖掘零售交易数据; 各个国家的总销售额分布情况; 11-9

(4)销量最高的10个商品

编号为84077的商品销量最高,达到53215件;销量Top3的商品在数量上差距并不大。

使用Spark分析挖掘零售交易数据; 销量最高的10个商品; 11-10

(5)商品描述的热门关键词Top300

热门关键词包括bag、red、heart、pink、christmas、cake等。

使用Spark分析挖掘零售交易数据; 商品描述的热门关键词Top300; 11-11

(6)退货订单数最多的10个国家

英国的退货订单最多,达到3208个,远大于其他国家;其次是德国、法国、爱尔兰等。

使用Spark分析挖掘零售交易数据; 退货订单数最多的10个国家; 11-12

(7)月销售额随时间的变化趋势

销售额较高的月份主要集中在下半年;由于该公司主要售卖礼品,并且下半年的节日较多,所以销售额比上半年高;2011年12月的销售额较低是因为数据只统计到2011/12/9 。

使用Spark分析挖掘零售交易数据; 月销售额随时间的变化趋势; 11-13

(8)日销量随时间的变化趋势

下半年的日销量整体上高于上半年;2011年10月5号达到日销量的最高纪录45741件。

使用Spark分析挖掘零售交易数据; 日销量随时间的变化趋势; 11-14

(9)各国的购买订单量和退货订单量的关系

购买订单量越大的国家,退货订单量往往也越大。

使用Spark分析挖掘零售交易数据; 各国的购买订单量和退货订单量的关系; 11-15

(10)商品的平均单价与销量的关系

总体上看,商品的销量随着平均单价的升高而下降。

6.参考资料

【大数据技术与处理】推荐阅读

ShowMeAI 系列教程推荐

图解大数据 | 大数据生态与应用导论 随着互联网高速发展,网络数据呈现出指数级别的快速增长,针对海量数据处理的大数据解决方案应运而生。ShowMeAI将在接下来的内容中逐步展开讲解大数据生态工具的应用,以及大数据的处理分析挖掘方法。... 阅读详情

相关推荐

Spark在数据科学中的应用案例分析

图数据分析是数据科学中的另一个重要领域,而Spark的图计算框架GraphX提供了强大的图数据处理和分析能力。通过合理地利用Spark的计算能力和优化策略,可以高效地处理大规模数据集,并从中挖掘出有价值的信息,为决策提供支持。在上述代码中,我们使用Spark MLlib中的逻辑回归算法进行模型训练,并通过准确率评估了模型的性能。机器学习是数据科学领域的热点之一,而Spark提供了强大的机器学习库MLlib,支持各种常见的机器学习算法。通过Spark的并行计算能力,可以高效地训练大规模的机器学习模型。

liqinkuaia的博客 1496

基于Spark电商数据分析的设计与实现(毕业设计和环境搭建、代码完整)

课题:基于Spark电商数据分析的设计与实现需求:1、分析电商页面跳转情况 2、分析用户session情况 3、热门品类分析  本课程提供了对应的环境搭建、代码、数据库脚本等,适合大学毕业生的毕设设计和想了解大数据的学员学习观看。课题来源某211高校毕业学生,学员可以进行二次开发。 

基于Spark的企业订单数据分析

大数据实验教学系统案例:企业订单数据分析现有某公司销售数据集,包含orders、order details和products数据。其中:830个orders和2,155个order details。现公司领导提出,希望大数据分析部门通过分析该销售数据集,回答以下问题: • 每个客户下了多少订单? • 每个国家的订单有多少? • 每月(年)有多少订单? • 每个客户的年销售总额是多少? • 客户每年的平均订单是多少?本案例用到的数据集说明如下:   订单数据集文件:/data/dataset/nw/NW-Or

需要远程指导仿真实验、代码有问题的,请后台私信或者关注公众号 3483

“泰迪杯”超市Spark数据处理和数据分析项目实战Dataframe

“泰迪杯”超市Spark数据处理和数据分析项目实战Dataframe

m0_67144365的博客 3025

【信息科学与工程学】【数据科学】数据科学领域 第六篇 算法设计 01

算法设计

weixin_49199313的博客 1504

【信息科学与工程学】计算机科学与自动化-——第十五篇云计算 11 算法篇

在百万级虚拟机、百万级租户的超大规模云环境中,核心算法挑战包括:挑战维度具体问题算法需求技术复杂度规模性​百万级对象并发管理分布式算法、分区算法极高(NP-hard问题)多租户​租户间隔离与资源共享公平性算法、隔离算法高(多目标优化)动态性​资源需求实时变化自适应算法、在线算法高(实时决策)异构性​硬件/负载/需求差异分类算法、匹配算法中高(多维度优化)经济性​资源利用率与成本平衡优化算法、博弈论算法高(多目标博弈)以下是按领域分类的详细算法列表:算法名称数学建模表达核心思想时间复杂度适用场景推理步骤首次适

weixin_49199313的博客 1406

2026 届大数据专业毕设选题推荐,毕业设计题目汇总

042-springboot基于spring boot的软件学院学生成绩管理系统的设计与实现。186_springboot基于springboot的一个在线环保意识教育平台的设计与实现。springboot基于Spring Boot的食品安全信息管理系统的设计与实现7icc4。062-springboot基于springboot的青少年心理健康教育网站的设计与实现。069-springboot基于springboot的游戏创意工坊与推广平台的设计与实现。

JAVA编码选手的博客 2038

基于Spark的零售交易数据分析

该项目是大三下学期的课程设计,选取了共541909条数据,以Python为编程语言,使用大数据框架Spark对数据进行了预处理,然后分别从多个方面对数据进行了分类和分析,并对分析结果进行可视化。里面包含我的课程设计报告和完整的代码。希望对你们有帮助。

银行零售实时决策系统:Flink+Delta Lake+图神经网络架构实践

客户行为分析是金融大数据的核心基础能力,其本质是通过实时数据处理与动态意图建模,实现从静态标签到决策驱动的范式升级。技术上需融合事件流计算(如Flink)、ACID兼容数据湖(如Delta Lake)与关系网络挖掘(如图神经网络),解决银行业务中‘三重时效悖论’与数据血缘断裂等关键难题。该能力支撑信贷审批、财富推荐、反欺诈等高价值场景,并可延伸至监管科技、产品迭代与组织诊断。本文聚焦银行零售领域真实落地案例,详解如何构建低延迟、强一致、可解释的客户实时决策神经网络。

weixin_30425949的博客 862

基于spark的电商商品智能分析系统,采用流式计算电商商品关注度,实现商品智能推荐及关联分析.zip

本资源中的源码都是经过本地编译过可运行的,下载后按照文档配置好环境就可以运行。资源项目源码系统完整,内容都是经过专业老师审定过的,能够满足基本的学习、使用和参考需求,如果有需要的话可以放心下载使用。

CMap数据库实战:从基因表达谱到药物重定位的可视化分析

本文详细介绍了如何利用CMap数据库进行药物重定位的可视化分析。通过实战演示,从差异基因列表准备、CMap查询参数设置,到结果筛选与高级可视化(如热图与OncoPrint风格图),系统讲解了从数据到洞察的全流程,并提供了关键的解读与验证指南,帮助研究者高效挖掘老药新用的潜力。

mango的博客 591

软件工程专业毕业设计选题大全 毕设指导

本文摘要了一系列基于Django、JSPM、Node.js、PHP、Python和SpringBoot框架开发的Web应用系统,涵盖多个领域:1)教育类(考研学习、在线考试、职业推荐);2)电商类(商城、二手交易、购物分析);3)管理系统(学生选课、人事管理、固定资产);4)数据分析(旅游景点、销售数据、气象预测);5)社交平台(音乐分享、动漫社区);6)公共服务(养老、医疗、法律援助)。这些系统充分发挥了各类技术栈的优势,如Django的后台处理能力、SpringBoot的微服务特性,针对特定行业需求提供

全网粉丝10W+、全栈领域优质创作者、掘金、阿里云等社区博客专家、专注于全栈领域和毕业项目实战 1378

python123题目——个税计算器

类型:简单分支。

m0_62488776的博客 5806

2025-2026年计算机毕业设计选题推荐:200+个热门精品毕设题目

042-springboot基于spring boot的软件学院学生成绩管理系统的设计与实现。186_springboot基于springboot的一个在线环保意识教育平台的设计与实现。springboot基于Spring Boot的食品安全信息管理系统的设计与实现7icc4。062-springboot基于springboot的青少年心理健康教育网站的设计与实现。069-springboot基于springboot的游戏创意工坊与推广平台的设计与实现。

xn19950718的博客 4216

PHP实战:5分钟搞定SM4国密加密算法集成(附完整代码)

本文提供了一份可直接用于生产环境的PHP SM4国密加密算法集成实战指南。文章详细解析了SM4算法核心,对比了ECB与CBC工作模式,并给出了包含完整代码、密钥管理、数据填充及性能优化的解决方案,帮助开发者快速、安全地在PHP项目中集成国密加密算法。

2a4s6d8f0g的博客 343

CRaxsRat v7.6 安装与使用教程(附工具下载)

摘要:本文介绍远程管理工具CRaxsRat v7.6的合法应用与基本操作,强调仅限授权环境使用。该工具支持多客户端管理、TLS加密及文件/进程控制等功能,适用于内网维护与安全测试。安装需Windows 10/11系统及.NET 4.8,步骤包括解压运行、配置监听端口及生成客户端。文中提醒防火墙设置与杀软误报问题,并重申禁止非法用途,建议在虚拟机或隔离环境学习使用。

lzj781210的博客 3796

Spark大数据分析实战-公司销售数据分析

文章目录需求一、数据字段说明1.1 日期数据1.2 订单头数据1.3 订单明细数据二、分析步骤2.1 计算所有订单中每年的销售单数、销售总额。2.2 计算所有订单中每年的最大金额订单的销售额。2.3 计算所有订单中每年最畅销的货品。2.4 全部代码三、总结 需求 假设某公司为你提供以下数据,改数据包括3个.txt文档数据,分别为日期数据、订单头数据、订单明细数据。让你根据公司所提供的的数据进行如下的需求分析。 1.计算所有订单中每年的销售单数、销售总额。 2.计算所有订单每年最大金额订单的销售额。 3..

wangbowen2000的博客 6066

如何使用Dify 搭建一个用自然语言查询数据库的 Agent?

这样就会发布完毕。

AI Agent 首席体验官 1700

Hadoop大数据综合案例4-Hive数据分析

大数据价值链中最重要的一个环节就是数据分析,其目标是提取数据中隐藏的数据,提供有意义的建议以辅助制定正确的决策。通过数据分析,人们可以从杂乱无章的数据中萃取和提炼有价值的信息,进而找出研究对象的内在规律。 数据分析是指用适当的统计分析方法对收集来的大量数据进行分析,从行业角度看,数据分析是基于某种行业目的,有目的的进行收集、整理、加工和分析数据的过程,通过提取有用信息,从而形成相关结论,这一过程也是质量管理体系的支持过程。数据分析的作用包含推测或解释数据并确定如何使用数据、检查数据是否合法、为决策提供参考建

CDHong.it的技术分享博客 1万+

YOLOv8中Bottleneck模块详解

Bottleneck 模块在YOLOv8中的作用是进行特征提取和增强,是网络中的核心构建模块之一。它的主要功能是通过卷积操作来处理输入特征图,并在适当情况下应用残差连接,使得信息能够有效地通过网络层进行传播

zzzyyy8的博客 8067

30. 如何使用 SEGW 的 redefine 功能对 SAP 标准 OData 服务进行扩展

SAP 发布了很多标准的 Fiori 应用,可以通过笔者的文章里提到的进行浏览。比如 My Opportunities 就是 SAP CRM 领域的一个 Fiori 应用:下图是 Opportunity 明细页面的 Info 标签页:假设我们想在这些标准字段的末尾增添一个新字段 Created By,用来维护当前 Opportunity 的创建者。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1176

基于Spark(Python版)的零售交易数据分析

简要,并不全面

weixin_51872564的博客 1315

【Unity实战篇】 接入百度翻译,实现文本自动翻译功能

日常在做项目的过程中,游戏本地化几乎已经成为必不可少的一步。 本篇文章将演示怎样在Unity中接入百度翻译,实现文本自动翻译的功能。

努力前行,总会成为自己心中的那道光 9061

基于SPARK的淘宝用户购物行为可视化分析(调优版一)

基于SPARK的淘宝用户购物行为可视化分析调优版,实验基于搭建的虚拟机集群,针对其中一条SQL转换成RDD形式进行调优,调优前后运行时间从200s降低至140s,有点效果!

番茄薯仔 1322

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

基于PySpark的销量预测

“ 本文阐述基于Pyspark的sql数据读取、特征处理、寻找最优参数、使用最优参数预测未来销量的全过程,重在预测流程和Pyspark相关知识点的讲解,展示可供企业级开发落地的demo。”

fitzgerald0的博客 2538

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

上一篇: 图解大数据 | 基于Spark RDD的大数据处理分析
下一篇: 图解大数据 | 综合案例-使用Spark分析挖掘音乐专辑数据
ShowMeAI
博客等级 码龄5年 6514粉丝 672原创
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShowMeAI

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值