计算机毕设卡壳?《基于大数据的优衣库销售数据分析系统》技术路线+代码一步到位【Hadoop、Spark、Python】

精彩专栏推荐订阅:在下方主页👇🏻👇🏻👇🏻👇🏻

💖🔥作者主页计算机毕设木哥🔥 💖

一、项目介绍

过去三年,优衣库大中华区的年营收从 4587 亿日元抬升到 5385 亿日元,线上订单占比却仅徘徊在 12%~15%,线下门店依旧是吸金主力。观远 BI 的跟踪报告披露,2023 年 2 万 2 千多条门店小票数据里,T 恤与配件贡献了 73% 利润,而北京市场的牛仔裤、运动系列利润不足千元,库存周转天数比深圳多 11 天。区域差异、品类冷热、渠道分流在同一组数据里反复碰撞,却缺少一条能把人、货、场真正串起来的高速通路。Hadoop+Spark 的组合恰好能把这些分散在 POS、小程序、ERP 里的异构日志汇聚成可运算的体量,补上传统 BI 报表“看数快、算数慢”的短板。

把这套技术搬到毕业设计里,不只是为了跑通一个“高大上”的演示。优衣库门店每天都要根据头一天的销售数据决定补货量,早一分钟拿到区域销量热力图,就能少压十件库存;Python+Django 把 Spark 的离线结果封装成可调用的 REST 接口,前端用 Vue+Echarts 把数据投到大屏,技术栈可以在不增加额外服务器预算的情况下,把原本需要 T+3 的决策周期压到 T+0,让库存、营销、陈列的每一环都能听见数据的回声。

二、视频展示

计算机毕设卡壳?《基于大数据的优衣库销售数据分析系统》技术路线+代码一步到位【Hadoop、Spark、Python】

三、开发环境

  • 大数据技术:Hadoop、Spark、Hive
  • 开发技术:Python、Django框架、Vue、Echarts
  • 软件工具:Pycharm、DataGrip、Anaconda
  • 可视化 工具 Echarts

四、系统展示

登录模块:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、代码展示


from pyspark.sql import SparkSession

from pyspark.sql.functions import (

    col, sum as _sum, avg, count, when, lag, datediff,

    date_format, max as _max, min as _min, round as _round

)

from pyspark.sql.window import Window

import os



spark = (

    SparkSession.builder

    .appName("uniqlo_real_screenshot_pipeline")

    .enableHiveSupport()

    .getOrCreate()

)



RAW_PATH = "hdfs://namenode:9000/uniqlo/sales_raw/*.parquet"

INV_PATH = "hdfs://namenode:9000/uniqlo/inventory/*.parquet"

OUT_BASE = "hdfs://namenode:9000/uniqlo/output"



def build_overall_kpi_and_trend():

    df = spark.read.parquet(RAW_PATH)

    df = df.filter(col("order_date").between("2023-01-01", "2024-06-30"))

    df = (

        df.withColumn("net_sales", col("qty") * col("unit_price"))

          .withColumn("profit", col("net_sales") - col("cost"))

    )



    # KPI

    kpi = (

        df.agg(

            _sum("net_sales").alias("total_sales"),

            _sum("profit").alias("total_profit"),

            count("*").alias("total_orders"),

            countDistinct("customer_id").alias("total_customers")

        )

    )

    kpi.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/overall_kpi")



    # 月度趋势

    monthly = (

        df.groupBy(date_format("order_date", "yyyy-MM").alias("month"))

          .agg(

              _sum("net_sales").alias("sales"),

              _sum("profit").alias("profit")

          )

          .orderBy("month")

    )

    monthly.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/monthly_trend")





def build_product_analysis():

    df = spark.read.parquet(RAW_PATH)

    df = (

        df.withColumn("net_sales", col("qty") * col("unit_price"))

          .withColumn("profit", col("net_sales") - col("cost"))

    )



    # 品类排行

    category_rank = (

        df.groupBy("product_category")

          .agg(

              _sum("net_sales").alias("total_sales"),

              _sum("profit").alias("total_profit"),

              (_sum("profit") / _sum("net_sales") * 100).alias("profit_margin")

          )

          .orderBy(col("total_sales").desc())

    )

    category_rank.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/category_rank")



    # 负利润明细

    negative_profit = (

        df.filter(col("profit") < 0)

          .groupBy("city", "product_category")

          .agg(

              _sum("net_sales").alias("sales"),

              _sum("profit").alias("loss")

          )

          .orderBy("city", "product_category")

    )

    negative_profit.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/negative_profit")



def build_region_channel_analysis():

    df = spark.read.parquet(RAW_PATH)

    df = (

        df.withColumn("net_sales", col("qty") * col("unit_price"))

          .withColumn("profit", col("net_sales") - col("cost"))

    )



    # 城市销售排行

    city_rank = (

        df.groupBy("city")

          .agg(_sum("net_sales").alias("sales"))

          .orderBy(col("sales").desc())

    )

    city_rank.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/city_rank")



    # 渠道销售构成

    channel_contrib = (

        df.groupBy("channel")

          .agg(

              _sum("net_sales").alias("sales"),

              (_sum("net_sales") / df.agg(_sum("net_sales")).collect()[0][0] * 100).alias("pct")

          )

    )

    channel_contrib.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/channel_contrib")



    # 城市×品类热力矩阵

    city_category = (

        df.groupBy("city", "product_category")

          .agg(_sum("net_sales").alias("sales"))

    )

    city_category.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/city_category_heatmap")



    # 渠道品类差异

    channel_category = (

        df.groupBy("channel", "product_category")

          .agg(_sum("net_sales").alias("sales"))

    )

    channel_category.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/channel_category")





def build_store_rfm():

    df = spark.read.parquet(RAW_PATH)

    df = df.withColumn("net_sales", col("qty") * col("unit_price"))



    # 以门店为粒度聚合 RFM

    rfm = (

        df.groupBy("store_id")

          .agg(

              datediff("2024-06-30", _max("order_date")).alias("recency"),

              count("*").alias("frequency"),

              _sum("net_sales").alias("monetary")

          )

    )



    # 分位点

    rec_q = rfm.approxQuantile("recency", [0.5], 0.01)[0]

    freq_q = rfm.approxQuantile("frequency", [0.5], 0.01)[0]

    mon_q = rfm.approxQuantile("monetary", [0.5], 0.01)[0]



    rfm = (

        rfm.withColumn("R_score", when(col("recency") < rec_q, 2).otherwise(1))

           .withColumn("F_score", when(col("frequency") > freq_q, 2).otherwise(1))

           .withColumn("M_score", when(col("monetary") > mon_q, 2).otherwise(1))

           .withColumn("score", col("R_score") + col("F_score") + col("M_score"))

    )



    segment_expr = (

        when(col("score") == 6, "重要价值门店")

        .when(col("score") == 5, "重要发展门店")

        .when(col("score") == 4, "重要保持门店")

        .when(col("score") == 3, "重要挽留门店")

        .when(col("score") == 2, "流失风险门店")

        .otherwise("需重点激活门店")

    )

    rfm = rfm.withColumn("segment", segment_expr)

    rfm.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/store_rfm")







def build_customer_profile():

    df = spark.read.parquet(RAW_PATH)

    df = df.withColumn("net_sales", col("qty") * col("unit_price"))



    # 性别贡献

    gender_contrib = (

        df.groupBy("gender")

          .agg(_sum("net_sales").alias("sales"))

    )

    gender_contrib.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/gender_contrib")



    # 年龄贡献

    age_contrib = (

        df.groupBy("age_group")

          .agg(_sum("net_sales").alias("sales"))

          .orderBy("age_group")

    )

    age_contrib.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/age_contrib")



    # 客单价

    age_avg = (

        df.groupBy("age_group")

          .agg((_sum("net_sales") / count("*")).alias("avg_order_value"))

          .orderBy("age_group")

    )

    age_avg.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/age_avg_order")





def build_weekday_weekend():

    df = spark.read.parquet(RAW_PATH)

    df = df.withColumn("net_sales", col("qty") * col("unit_price"))

    df = df.withColumn("week_part", date_format("order_date", "u").cast("int"))

    df = df.withColumn("week_part", when(col("week_part") < 6, "工作日").otherwise("周末"))



    weekday_weekend = (

        df.groupBy("week_part", "product_category")

          .agg(_sum("net_sales").alias("sales"))

    )

    weekday_weekend.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/weekday_weekend")







def build_price_sensitivity():

    df = spark.read.parquet(RAW_PATH)

    df = (

        df.withColumn("net_sales", col("qty") * col("unit_price"))

          .withColumn("profit", col("net_sales") - col("cost"))

    )



    price_sens = (

        df.groupBy("product_category")

          .agg(

              avg("unit_price").alias("avg_price"),

              (_sum("profit") / _sum("net_sales") * 100).alias("profit_margin")

          )

    )

    price_sens.coalesce(1).write.mode("overwrite").json(f"{OUT_BASE}/price_sensitivity")

六、项目文档展示

在这里插入图片描述

七、项目总结

一路做下来,这套《基于大数据的优衣库销售数据分析系统》把“看数”真正变成了“用数”。Hadoop 与 Spark 扛住千万级小票,Python+Django 把复杂逻辑封装成可调接口,Vue+Echarts 把城市热力、品类盈亏、RFM 门店分级一次性推到浏览器和大屏。不再是静态数字,而是可下钻、可预警、可行动的活数据。项目验证了从原始日志到商业洞察的完整闭环,也证明了毕业设计不必堆技术名词,只要围绕真实业务痛点,一套简洁而聚焦的栈就能让数据说话。

大家可以帮忙点赞、收藏、关注、评论啦 👇🏻

💖🔥作者主页:计算机毕设木哥🔥 💖

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值