外卖大数据案例
一、环境要求 Hadoop+Hive+Spark+HBase 开发环境。
二、数据描述
meituan_waimai_meishi.csv 是某外卖平台的部分外卖 SPU(Standard Product Unit , 标准产品单元)数据,包含了外卖平台某地区一时间的外卖信息。具体字段说明如下:
| 字段名称 | 中文名称 | 数据类型 |
| spu_id | 商品spuID | String |
| shop_id | 店铺ID | String |
| shop_name | 店铺名称 | String |
| category_name | 类别名称 | String |
| spu_name | SPU名称 | String |
| spu_price | SPU商品售价 | Double |
| spu_originprice | SPU商品原价 | Double |
| month_sales | 月销售量 | Int |
| praise_num | 点赞数 | Int |
| spu_unit | SPU单位 | String |
| spu_desc | SPU描述 | String |
| spu_image | 商品图片 | String |
三、功能要求
1.数据准备
在 HDFS 中创建目录/app/data/exam,并将 meituan_waimai_meishi.csv 文件传到该 目录。并通过 HDFS 命令查询出文档有多少行数据。
启动Hadoop
[root@kb135 ~]# start-all.sh
退出安全模式
[root@kb135 ~]# hdfs dfsadmin -safemode leave
上传文件
[root@kb135 examdata]# hdfs dfs -put ./meituan_waimai_meishi.csv /app/data/exam
查看数据行数
[root@kb135 examdata]# hdfs dfs -cat /app/data/exam/meituan_waimai_meishi.csv | wc -l
2.使用 Spark加载 HDFS 文件
加载meituan_waimai_meishi.csv 文件,并分别使用 RDD 和 Spark SQL 完成以下分析(不用考虑数据去重)。
Rdd:
启动spark
[root@kb135 ~]# spark-shell
创建Rdd
scala> val fileRdd = sc.textFile("/app/data/exam/meituan_waimai_meishi.csv")
清洗数据
scala> val spuRdd = fileRdd.filter(x=>x.startsWith("spu_id")==false).map(x=>x.split(",",-1)).filter(x=>x.size==12)
①统计每个店铺分别有多少商品(SPU)。
scala> spuRdd.map(x=>(x(2),1)).reduceByKey(_+_).collect.foreach(println)

②统计每个店铺的总销售额。
scala> spuRdd.map(x=>(x(2),x(5).toDouble*x(7).toInt)).filter(x=>x._2>0).reduceByKey(_+_).collect.foreach(println)

③统计每个店铺销售额最高的前三个商品,输出内容包括店铺名,商品名和销售额,其 中销售额为 0 的商品不进行统计计算,例如:如果某个店铺销售为 0,则不进行统计。
scala> spuRdd.map(x=>(x(2),x(4),x(5).toDouble*x(7).toInt)).filter(x=>x._3>0).groupBy(x=>x._1).mapValues(x=>x.toList.sortBy(item=>0-item._3).take(3)).flatMapValues(x=>x).map(x=>x._2).collect.foreach(println)

scala> spuRdd.map(x=>(x(2),x(4),x(5).toDouble*x(7).toInt)).filter(x=>x._3>0).groupBy(x=>x._1).flatMap(x=>{x._2.toList.sortBy(item=>0-item._3).take(3)}).collect.foreach(println)

scala> spuRdd.map(x=>(x(2),x(4),x(5).toDouble*x(7).toInt)).filter(x=>x._3>0).groupBy(x=>x._1).map(x=>{x._2.toList.sortBy(item=>0-item._3).take(3) }).flatMap(x=>x).collect.foreach(println)

---------------------------------------------------------------------------------------------------------------------------------
spark sql:
①统计每个店铺分别有多少商品(SPU)。
scala> spark.sql("select shop_name ,count(spu_name) as num from spu group by shop_name").show

②统计每个店铺的总销售额。
scala> spark.sql("select shop_name,sum(spu_price*month_sales) as money from spu where month_sales !=0 group by shop_name").show

③统计每个店铺销售额最高的前三个商品,输出内容包括店铺名,商品名和销售额,其中销售额为 0 的商品不进行统计计算,例如:如果某个店铺销售为 0,则不进行统计。
scala> spark.sql("select t.shop_name,t.spu_name,t.money,t.rn from (select shop_name,spu_name,spu_price*month_sales as money,row_number() over(partition by shop_name order by spu_price*month_sales desc) as rn from spu where month_sales != 0) t where t.rn<4").show(100)

3.创建 HBase 数据表
在 HBase 中创建命名空间(namespace)exam,在该命名空间下创建 spu 表,该表下有
1 个列族 result。
启动zookeeper
[root@kb135 ~]# zkServer.sh start
启动hbase
[root@kb135 examdata]# start-hbase.sh
[root@kb135 examdata]# hbase shell
创建表空间
hbase(main):002:0> create_namespace 'exam202009'
创建表
hbase(main):003:0> create 'exam202009:spu','result'
4.在 Hive 中创建数据库 spu_db
在该数据库中创建外部表 ex_spu 指向 /app/data/exam 下的测试数据 ;创建外部表 ex_spu_hbase 映射至 HBase 中的 exam:spu 表的 result 列族
ex_spu 表结构如下:
| 字段名称 | 中文名称 | 数据类型 |
| spu_id | 商品spuID | string |
| shop_id | 店铺ID | string |
| shop_name | 店铺名称 | string |
| category_name | 类别名称 | string |
| spu_name | SPU名称 | string |
| spu_price | SPU商品价格 | double |
| spu_originprice | SPU商品原价 | double |
| month_sales | 月销售量 | int |
| praise_num | 点赞数 | int |
| spu_unit | SPU单位 | string |
| spu_desc | SPU描述 | string |
| spu_image | 商品图片 | string |
ex_spu_hbase 表结构如下:
| 字段名称 | 字段类型 | 字段含义 |
| key | string | rowkey |
| sales | double | 销售额 |
| praise | int | 点赞数 |
创建表语句:
create external table if not exists ex_spu(
spu_id string,
shop_id string,
shop_name string,
category_name string,
spu_name string,
spu_price double,
spu_originprice double,
month_sales int,
praise_num int,
spu_unit string,
spu_desc string,
spu_image string
)
row format delimited fields terminated by ","
stored as textfile location "/app/data/exam"
tblproperties("skip.header.line.count"="1");
create external table if not exists ex_spu_hbase(
key string,
sales double,
praise int
)
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler' with
serdeproperties("hbase.columns.mapping"=":key,result:sales,result:praise")
tblproperties("hbase.table.name"="exam202009:spu");
5. 统计查询
①统计每个店铺的总销售额 sales, 店铺的商品总点赞数 praise,并将 shop_id 和 shop_name 的组合作为 RowKey,并将结果映射到 HBase。
插入数据:
hive (spu_db)> insert into ex_spu_hbase (select concat(shop_id,shop_name) as key ,sum(spu_price*month_sales) as sales,sum(praise_num) as praise from ex_spu group by shop_id,shop_name);
②完成统计后,分别在 hive 和 HBase 中查询结果数据。
hive (spu_db)> select * from ex_spu_hbase;
hbase(main):005:0> scan 'exam202009:spu'
相关文章:
外卖大数据案例
一、环境要求 HadoopHiveSparkHBase 开发环境。 二、数据描述 meituan_waimai_meishi.csv 是某外卖平台的部分外卖 SPU(Standard Product Unit , 标准产品单元)数据,包含了外卖平台某地区一时间的外卖信息。具体字段说明如下&am…...
到底什么是5G-R?
近日,工信部向中国国家铁路集团有限公司(以下简称“国铁集团”)批复5G-R试验频率的消息,引起了行业内的广泛关注。 究竟什么是5G-R?为什么工信部会在此时批复5G-R的试验频率? 今天,小枣君就通过…...
uniapp 使用和引入 thorui
1. npm install thorui-uni 2. "easycom": { "autoscan": true, "custom": { "tui-(.*)": "thorui-uni/lib/thorui/tui-$1/tui-$1.vue" } }, 3....
vue3中ref和reactive的区别
原文地址 深入聊一聊vue3中的reactive()_vue3 reactive_忧郁的蛋~的博客-CSDN博客 ref和reactive的区别-CSDN博客 理解: 1.ref是定义简单类型 和单一的对象 2.reactive 定义复杂的类型 梳理文档: ref和reactive都是Vue.js 3.x版本中新增的响应式API&…...
文件路径操作
避开-转义字符 python文件路径导致的错误常常与“\”有关,因为在路径中的“\”常会被误认为转义字符。 所以在上述路径中,\table\name\rain中的\t,\n,\r都易被识别为转义字符。 解决的办法主要由以下三种: #1 前面加r表示不转义 pathr&quo…...
Java Cache 缓存方案详解及代码-Ehcache
一、Spring缓存概念 Spring从3.1开始定义了 org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 接口来统一不同的缓存技术; 并支持使用 JCache(JSR-107) 注解简化我们开发。 常用的缓存实现有 RedisCache 、EhCach…...
JAVA设计模式-装饰者模式
一.概念 装饰器模式(Decorator Pattern),动态地给一个对象添加一些额外的职责,就增加功能来说,装饰器模式比生成子类更灵活。 —-《大话设计模式》 允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属…...
STM32F1简介
前言 本次学习使用的是STM32F1系列的芯片,72MHz的Cortex-M3内核; 名词解释 STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器(MCU); ARM Cortex-M内核是ARM公司设计的,程序指令的执行,…...
SpringBoot面试题6:Spring Boot 2.X 有什么新特性?与 1.X 有什么区别?
该文章专注于面试,面试只要回答关键点即可,不需要对框架有非常深入的回答,如果你想应付面试,是足够了,抓住关键点 面试官:Spring Boot 2.X 有什么新特性?与 1.X 有什么区别? Spring Boot是一种用于简化Spring应用程序开发的框架,它提供了自动配置、起步依赖和快速开…...
qt笔记之qml下拉标签组合框增加发送按钮发送标签内容
qt笔记之qml下拉标签组合框增加发送按钮发送标签内容 code review! 文章目录 qt笔记之qml下拉标签组合框增加发送按钮发送标签内容1.运行2.文件结构3.main.qml4.main.cc5.MyClass.h6.MyClass.cc7.CMakeLists.txt8.ComboBox.pro9.qml.qrc 1.运行 2.文件结构 3.main.qml 代码 …...
linux上构建任意版本的rocketmq多架构x86 arm镜像——筑梦之路
现状 目前市面上和官方均只有rocketmq x86架构下的docker镜像,而随着国产化和信创适配的需求越来越多,显然现有的x86架构下的docker镜像不能满足多样化的需求,因此我们需要根据官方发布的版本制作满足需求的多架构镜像,以在不同cp…...
Java8 新特性之Stream(五)-- Stream的3种创建方法
目录 1. 集合 创建Stream流 拓展: 2. 数组 创建Stream流 3. 静态方法 创建Stream流 1. 集合 创建Stream流 @...
Vue实现模糊查询搜索功能
第一步 先创建一个val变量 // 用户搜索内容 let val ref(""); 第二步:给input绑定v-model (为了获取input框的值) <input v-model"val" type"text" placeholder"请输入行业/公司/名称"/> 第…...
(C++ STL) 详解vector模拟实现
目录 一.vector的介绍 1.vector的介绍 二.vector的定义模拟实现 三.vector各接口的模拟实现 1.vector迭代器的模拟实现 2.构造函数 2.1无参构造 2.2 n个val构造 2.3迭代器区间构造 2.4通过对象初始化(拷贝构造) 3.析构函数 4.size 5.operato…...
c语言从入门到实战——C语言数据类型和变量
C语言数据类型和变量 前言1. 数据类型介绍1.1 字符型1.2 整型1.3 浮点型1.4 布尔类型1.5 各种数据类型的长度1.5.1 sizeof操作符1.5.2 数据类型长度1.5.3 sizeof中表达式不计算 2. signed 和 unsigned3. 数据类型的取值范围4. 变量4.1 变量的创建4.2 变量的分类 5. 算术操作符&…...
[论文精读]Semi-Supervised Classification with Graph Convolutional Networks
论文原文:[1609.02907] Semi-Supervised Classification with Graph Convolutional Networks (arxiv.org) 论文代码:GitHub - tkipf/gcn: Implementation of Graph Convolutional Networks in TensorFlow 英文是纯手打的!论文原文的summari…...
CICD:使用docker+ jenkins + gitlab搭建cicd服务
持续集成解决什么问题 提高软件质量效率迭代便捷部署快速交付、便于管理 持续集成(CI) 集成,就是一些孤立的事物或元素通过某种方式集中在一起,产生联系,从而构建一个有机整体的过程。 持续,就是指长期…...
新能源电池试验中准确模拟高空环境大气压力的解决方案
摘要:针对目前新能源电池热失控和特性研究以及生产中缺乏变环境压力准确模拟装置、错误控制方法造成环境压力控制极不稳定以及氢燃料电池中氢气所带来的易燃易爆问题,本文提出了相应的解决方案。方案的关键一是采用了低漏率电控针阀作为下游控制调节阀实…...
Python 中的模糊字符串匹配
文章目录 Python中使用thefuzz模块匹配模糊字符串使用process模块高效地使用模糊字符串匹配今天,我们将学习如何使用 thefuzz 库,它允许我们在 python 中进行模糊字符串匹配。 此外,我们将学习如何使用 process 模块,该模块允许我们借助模糊字符串逻辑有效地匹配或提取字符…...
记录一个奇怪bug
一开始Weapon脚本是继承Monobehavior的,实例化后挂在gameObject上跟着角色。后来改成了不继承mono的,也不实例化。过程都是顺利的,运行也没问题,脚本编辑器也没有错误。 但偶尔有一次报了一些错误,大概是说Weapon (1)…...
告别标注烦恼:用DINOv2自监督模型,在Intel Image数据集上3个epoch实现93%准确率
零标注成本实战:DINOv2自监督模型在Intel Image数据集上的高效迁移方案 当我在实验室第一次尝试用传统方法训练一个图像分类模型时,面对数千张需要手动标注的图片,几乎要放弃这个课题。直到发现了自监督学习这个宝藏领域——特别是DINOv2这样…...
OpenClaw操作录制:ollama-QwQ-32B学习人工流程生成自动化脚本
OpenClaw操作录制:ollama-QwQ-32B学习人工流程生成自动化脚本 1. 为什么需要操作录制功能 上周我在整理月度运营报告时,突然意识到自己正在重复第7次执行完全相同的操作流程:打开三个数据源表格→复制特定列→粘贴到汇总表→生成折线图→导…...
遇到“用户对AIAgent进行提示词注入”怎么办?
文章目录先理解什么是“提示词注入”图片里的防护方法(两层)第一层:System Prompt 先贴“封条”第二层:输出端再加“安检门”总结先理解什么是“提示词注入” 你可以把 Agent(智能助手) 想象成一个 严格遵…...
水库调度员必看:动态规划在月度发电计划中的5个避坑指南
水库调度员实战指南:动态规划在月度发电计划中的5个关键避坑策略 在水利工程领域,水库调度是一项集科学性、技术性和艺术性于一体的复杂工作。作为水库调度员,我们每天都在与时间、水量和电力需求进行着精妙的博弈。而动态规划作为一种强大的…...
别再死记硬背了!用Python和SymPy库5分钟可视化理解泰勒公式的逼近过程
用Python动态可视化泰勒公式:5行代码理解多项式逼近本质 数学公式的抽象性常常成为学习者的障碍,尤其是泰勒公式这种涉及无限逼近概念的内容。传统的静态图示和理论推导虽然严谨,却难以直观展示"以直代曲"的动态过程。本文将用Pyth…...
MCprep插件终极指南:从Minecraft世界到专业动画的完整解决方案
MCprep插件终极指南:从Minecraft世界到专业动画的完整解决方案 【免费下载链接】MCprep Blender python addon to increase workflow for creating minecraft renders and animations 项目地址: https://gitcode.com/gh_mirrors/mc/MCprep 你是否曾梦想将Min…...
python基于微信小程序的旅游攻略分享平台
目录需求分析与功能规划技术架构设计数据库设计接口开发小程序前端开发部署与测试运营与迭代注意事项项目技术支持源码获取详细视频演示 :文章底部获取博主联系方式!同行可合作需求分析与功能规划 明确平台核心功能:用户注册登录、攻略发布与…...
Untrunc:10倍速视频修复工具,让损坏的MP4/MOV文件起死回生
Untrunc:10倍速视频修复工具,让损坏的MP4/MOV文件起死回生 【免费下载链接】untrunc Restore a truncated mp4/mov. Improved version of ponchio/untrunc 项目地址: https://gitcode.com/gh_mirrors/un/untrunc 你是否曾经因为视频文件损坏而失去…...
本地 AI 智能体落地:OpenClaw 如何稳定运行并真正提效?
最近我把 OpenClaw 作为核心自动化工具来使用了一段时间。它能让大模型直接操作电脑,跑脚本、处理文件、启动服务、执行批量任务,这种 “本地自动化” 体验非常真实。 但一开始我也被它的 “不稳定” 搞得很崩溃。 1. OpenClaw 的真正价值(…...
PyTorch实战:从零构建ResNet50模型(CIFAR10训练+测试+ONNX转换)
1. ResNet50模型基础认知 第一次接触ResNet50时,我被它的"残差连接"设计惊艳到了。传统神经网络随着层数增加会出现梯度消失问题,而ResNet通过跨层直连通道,让信息能够无损传递到更深层。这就好比在高速公路上设置应急车道…...
