(林子雨教程)淘宝双十一数据分析可视化部分错误处归纳解决与可视化进一步完善
(林子雨教程) Spark课程综合实验案例:淘宝双11数据分析与预测网址:
Spark课程综合实验案例:淘宝双11数据分析与预测_厦门大学数据库实验室 (xmu.edu.cn)
(林子雨教程)利用ECharts进行数据可视化分析网址:
淘宝双11数据分析与预测课程案例—步骤五:利用ECharts进行数据可视化分析_厦大数据库实验室博客 (xmu.edu.cn)
本人使用的相关软件版本如下:
Ubuntu版本:Ubuntu 24.04 LTS
java版本:1.8.0_412
mysql版本:8.0.37-0ubuntu0.24.04.1
eclipse版本:stable 2024-03
tomcat版本:V8.5
mysql-connector-java版本:mysql-connector-java-8.0.16
项目文档已放在文章末尾,需要的可自行食用~
一、出现前端网页打不开的情况
网页显示HTTP状态500 - 内部服务器错误
1.错误类型1
严重: 在路径为[/MyWebApp]的上下文中,Servlet[jsp]的Servlet.service()引发了具有根本原因的异常[java.lang.NullPointerException]
错误原因1:可能是mysql没启动。
解决方法1:命令行中输入service mysql start 启动mysql。
错误原因2:可能是connDb.java文件中
con = *DriverManager*.getConnection("jdbc:MySQL://localhost:3306/dbtaobao","root","root");
这里的第二个root没改。
解决方法2:
将第二个root改为登录mysql的密码。
2.错误类型2
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'desc' at line 1
错误原因:connDb.java文件中使用desc处的语法错误;desc是排序的关键字,要配合order排序指令一起使用。
解决方法: 将所有的desc前都加上order by num
将connDb.java中的代码修改为
package dbtaobao;
import java.sql.*;
import java.util.ArrayList;
public class connDb {
private static Connection con = null;
private static Statement stmt = null;
private static ResultSet rs = null;
//连接数据库方法
public static void startConn(){
try{
Class.forName("com.mysql.jdbc.Driver");
//连接数据库中间件
try{
con = DriverManager.getConnection("jdbc:MySQL://localhost:3306/dbtaobao","root","zkpk");
}catch(SQLException e){
e.printStackTrace();
}
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
//关闭连接数据库方法
public static void endConn() throws SQLException{
if(con != null){
con.close();
con = null;
}
if(rs != null){
rs.close();
rs = null;
}
if(stmt != null){
stmt.close();
stmt = null;
}
}
//数据库双11 所有买家消费行为比例
public static ArrayList index() throws SQLException{
ArrayList<String[]> list = new ArrayList();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select action,count(*) num from user_log group by action order by num desc"); // 修改处1
while(rs.next()){
String[] temp={rs.getString("action"),rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//男女买家交易对比
public static ArrayList index_1() throws SQLException{
ArrayList<String[]> list = new ArrayList();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select gender,count(*) num from user_log group by gender order by num desc"); // 修改处2
while(rs.next()){
String[] temp={rs.getString("gender"),rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//男女买家各个年龄段交易对比
public static ArrayList index_2() throws SQLException{
ArrayList<String[]> list = new ArrayList();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select gender,age_range,count(*) num from user_log group by gender,age_range order by num desc"); // 修改处3
while(rs.next()){
String[] temp={rs.getString("gender"),rs.getString("age_range"),rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//获取销量前五的商品类别
public static ArrayList index_3() throws SQLException{
ArrayList<String[]> list = new ArrayList();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select cat_id,count(*) num from user_log group by cat_id order by count(*) desc limit 5");
while(rs.next()){
String[] temp={rs.getString("cat_id"),rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//各个省份的的总成交量对比
public static ArrayList index_4() throws SQLException{
ArrayList<String[]> list = new ArrayList();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select province,count(*) num from user_log group by province order by count(*) desc");
while(rs.next()){
String[] temp={rs.getString("province"),rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
}
问题解决前与解决后对比:
二、男女买家各个年龄段交易对比散点图无数据
1.原因分析
根据connDb.java中这段代码
while(rs.next()){
String[] temp={rs.getString("gender"),rs.getString("age_range"),rs.getString("num")};
可以知道String[]中的数据包括性别,年龄段,和数量
String[0]表示性别
String[1]表示年龄段
String[2]表示数量
而在index2.jsp中,此处
for(String[] a:list){
if(a[0].equals("0")){
%>
data[0].push([<%=a[0]%>,<%=a[1]%>,<%=a[2]%>]); //多出来了a[0]
<%
}else if(a[0].equals("1")){
%>
data[1].push([<%=a[0]%>,<%=a[1]%>,<%=a[2]%>]); //多出来了a[0]
<%
}
}
已经用if判断男性和女性了,将a[0]放在data中多此一举了,不仅多此一举,而且还会造成之后数据读取错误的情况
数据点返回处
symbolSize: function (data) {
return Math.sqrt(data[2]) / 5e2;
},
其中symbolSize是用来计算每个点的数据大小的,返回值以像素为单位显示数据点大小,因为提取的数据是10000个,8个年龄段加上男女分配,每个点的数据大小平均不超过625,除以500,每个数据点的平均像素值一点多,在图上显示后肉眼不可见;将500改为6以下,数据点肉眼可见。
同时根据上面的分析,需要将data[2]改成data[1]
2.解决措施步骤
1.删掉push中a[0]
2.将return 中的data[2]改成data[1],5e2改成3
index2.jsp修改如下
<%@ page language="java" import="dbtaobao.connDb,java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
ArrayList<String[]> list = connDb.index_2();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ECharts 可视化分析淘宝双11</title>
<link href="./css/style.css" type='text/css' rel="stylesheet"/>
<script src="./js/echarts.min.js"></script>
</head>
<body>
<div class='header'>
<p>ECharts 可视化分析淘宝双11</p>
</div>
<div class="content">
<div class="nav">
<ul>
<li><a href="./index.jsp">所有买家各消费行为对比</a></li>
<li><a href="./index1.jsp">男女买家交易对比</a></li>
<li class="current"><a href="#">男女买家各个年龄段交易对比</a></li>
<li><a href="./index3.jsp">商品类别交易额对比</a></li>
<li><a href="./index4.jsp">各省份的总成交量对比</a></li>
</ul>
</div>
<div class="container">
<div class="title">男女买家各个年龄段交易对比</div>
<div class="show">
<div class='chart-type'>散点图</div>
<div id="main"></div>
</div>
</div>
</div>
<script>
//基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 指定图表的配置项和数据
var data = [];
data[0] = [];
data[1] = [];
<%
for(String[] a:list){
if(a[0].equals("0")){
%>
data[0].push([<%=a[1]%>,<%=a[2]%>]); //修改处1
<%
}else if(a[0].equals("1")){
%>
data[1].push([<%=a[1]%>,<%=a[2]%>]); //修改处2
<%
}
}
%>
option = {
backgroundColor: new echarts.graphic.RadialGradient(0.3, 0.3, 0.8, [{
offset: 0,
color: '#f7f8fa'
}, {
offset: 1,
color: '#cdd0d5'
}]),
title: {
text: '男女买家各个年龄段交易对比'
},
legend: {
right: 10,
data: ['women', 'men']
},
xAxis: {
splitLine: {
lineStyle: {
type: 'dashed'
}
}
},
yAxis: {
splitLine: {
lineStyle: {
type: 'dashed'
}
},
scale: true,
},
series: [{
name: 'women',
data: data[0],
type: 'scatter',
symbolSize: function (data) {
return Math.sqrt(data[1]) / 3; //修改处3
},
label: {
emphasis: {
show: true,
formatter: function (param) {
return param.data[3];
},
position: 'top'
}
},
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(120, 36, 50, 0.5)',
shadowOffsetY: 5,
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{
offset: 0,
color: 'rgb(251, 118, 123)'
}, {
offset: 1,
color: 'rgb(204, 46, 72)'
}])
}
}
}, {
name: 'men',
data: data[1],
type: 'scatter',
symbolSize: function (data) {
return Math.sqrt(data[1]) / 3; //修改处4
},
label: {
emphasis: {
show: true,
formatter: function (param) {
return param.data[3];
},
position: 'top'
}
},
itemStyle: {
normal: {
shadowBlur: 10,
shadowColor: 'rgba(25, 100, 150, 0.5)',
shadowOffsetY: 5,
color: new echarts.graphic.RadialGradient(0.4, 0.3, 1, [{
offset: 0,
color: 'rgb(129, 227, 238)'
}, {
offset: 1,
color: 'rgb(25, 183, 207)'
}])
}
}
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
3.问题解决前与解决后对比
三、类别交易额对比图名称错误
1.错误处
柱状图显示成了饼图
将index3.jsp中的
<div class='chart-type'>饼图</div>
改为
<div class='chart-type'>柱状图</div>
2.问题解决前与解决后对比
四、各省份的总成交量地图不显示以及代码缺失
1.步骤1
在js文件夹下添加china.js文件
文件下载地址
链接:https://pan.baidu.com/s/1W_S7dyn89MrZBEE3Ni7Plw?pwd=resy
提取码:resy
2.步骤2
修改index4.jsp中代码,修改后代码如下
<%@ page language="java" import="dbtaobao.connDb,java.util.*" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%
ArrayList<String[]> list = connDb.index_4();
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ECharts 可视化分析淘宝双11</title>
<link href="./css/style.css" type='text/css' rel="stylesheet"/>
<script src="./js/echarts.min.js"></script>
<script src="./js/china.js"></script>
</head>
<body>
<div class='header'>
<p>ECharts 可视化分析淘宝双11</p>
</div>
<div class="content">
<div class="nav">
<ul>
<li><a href="./index.jsp">所有买家各消费行为对比</a></li>
<li><a href="./index1.jsp">男女买家交易对比</a></li>
<li><a href="./index2.jsp">男女买家各个年龄段交易对比</a></li>
<li><a href="./index3.jsp">商品类别交易额对比</a></li>
<li class="current"><a href="#">各省份的总成交量对比</a></li>
</ul>
</div>
<div class="container">
<div class="title">各省份的总成交量对比</div>
<div class="show">
<div class='chart-type'>地图</div>
<div id="main"></div>
</div>
</div>
</div>
<script>
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 准备数据
var data = [];
<%
for(String[] a : list) {
%>
data.push(<%="{name:'"+a[0]+"',value:'"+a[1]+"'}"%>);
<%
}
%>
// 配置项
var option = {
backgroundColor: '#2c343c',
title: {
text: '各省份的总成交量对比',
left: 'center',
top: 20,
textStyle: {
color: '#ccc'
}
},
tooltip: {
trigger: 'item',
formatter: '{b}: {c}'
},
visualMap: {
min: 0,
max: 400,
left: 'left',
top: 'bottom',
text: ['高','低'],
calculable: true,
inRange: {
color: ['#50a3ba', '#eac736', '#d94e5d']
},
textStyle: {
color: '#ccc'
}
},
toolbox: {
show: true,
orient: 'vertical',
left: 'right',
top: 'center',
feature: {
dataView: {readOnly: false},
restore: {},
saveAsImage: {}
},
iconStyle: {
normal: {
color: '#ccc'
}
}
},
series: [
{
name: '销量',
type: 'map',
mapType: 'china',
roam: false,
label: {
show: true,
color: '#ccc'
},
itemStyle: {
normal: {
areaColor: '#323c48',
borderColor: '#111'
},
emphasis: {
areaColor: '#2a333d'
}
},
data: data
}
]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
3.问题解决前与解决后对比
五、增加回头客预测图
1.步骤1
在connnDb.java中添加回头客预测分数对比类代码,并导入相应的包,添加后完整代码如下
package dbtaobao;
import java.sql.*;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.Map;
public class connDb {
private static Connection con = null;
private static Statement stmt = null;
private static ResultSet rs = null;
//连接数据库方法
public static void startConn(){
try{
Class.forName("com.mysql.jdbc.Driver");
//连接数据库中间件
try{
con = DriverManager.getConnection("jdbc:MySQL://localhost:3306/dbtaobao","root","zkpk");
}catch(SQLException e){
e.printStackTrace();
}
}catch(ClassNotFoundException e){
e.printStackTrace();
}
}
//关闭连接数据库方法
public static void endConn() throws SQLException{
if(con != null){
con.close();
con = null;
}
if(rs != null){
rs.close();
rs = null;
}
if(stmt != null){
stmt.close();
stmt = null;
}
}
//数据库双11 所有买家消费行为比例
public static ArrayList<String[]> index() throws SQLException{
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select action,count(*) num from user_log group by action order by num desc");
while(rs.next()){
String[] temp = {rs.getString("action"), rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//男女买家交易对比
public static ArrayList<String[]> index_1() throws SQLException{
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select gender,count(*) num from user_log group by gender order by num desc");
while(rs.next()){
String[] temp = {rs.getString("gender"), rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//男女买家各个年龄段交易对比
public static ArrayList<String[]> index_2() throws SQLException{
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select gender,age_range,count(*) num from user_log group by gender,age_range order by num desc");
while(rs.next()){
String[] temp = {rs.getString("gender"), rs.getString("age_range"), rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//获取销量前五的商品类别
public static ArrayList<String[]> index_3() throws SQLException{
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select cat_id,count(*) num from user_log group by cat_id order by count(*) desc limit 5");
while(rs.next()){
String[] temp = {rs.getString("cat_id"), rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
//各个省份的的总成交量对比
public static ArrayList<String[]> index_4() throws SQLException{
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("select province,count(*) num from user_log group by province order by count(*) desc");
while(rs.next()){
String[] temp = {rs.getString("province"), rs.getString("num")};
list.add(temp);
}
endConn();
return list;
}
// 回头客预测分数对比
public static Map<String, Integer> index_5() throws SQLException {
ArrayList<String[]> list = new ArrayList<>();
startConn();
stmt = con.createStatement();
rs = stmt.executeQuery("SELECT `score`, `label` FROM `rebuy`");
// 获取最小值和最大值
double minScore = Double.MAX_VALUE;
double maxScore = Double.MIN_VALUE;
while(rs.next()){
double score = rs.getDouble("score");
if (score < minScore) {
minScore = score;
}
if (score > maxScore) {
maxScore = score;
}
String[] temp = {rs.getString("label"), String.valueOf(score)};
list.add(temp);
}
// 处理数据,计算标准化分数
ArrayList<Double> normalizedScores = new ArrayList<>();
for (String[] item : list) {
double originalScore = Double.parseDouble(item[1]);
double normalizedScore = ((originalScore - minScore) / (maxScore - minScore)) * 100;
normalizedScores.add(normalizedScore);
}
// 分成10个分数段,并计算每个分数段的人数
Map<String, Integer> scoreSegments = new LinkedHashMap<>();
for (int i = 0; i < 10; i++) {
scoreSegments.put((i * 10) + "-" + ((i + 1) * 10), 0);
}
for (double score : normalizedScores) {
int segment = (int) (score / 10);
if (segment == 10) segment = 9; // 处理100分的情况
String key = (segment * 10) + "-" + ((segment + 1) * 10);
scoreSegments.put(key, scoreSegments.get(key) + 1);
}
endConn();
return scoreSegments;
}
}
2.步骤2
在与index.jsp相同文件目录下添加index5.jsp代码,index5.jsp代码如下
<%@ page language="java" import="dbtaobao.connDb,java.util.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%
Map<String, Integer> scoreSegments = connDb.index_5(); // 获取处理后的数据
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>ECharts 可视化分析淘宝双11</title>
<link href="./css/style.css" type='text/css' rel="stylesheet"/>
<script src="./js/echarts.min.js"></script>
</head>
<body>
<div class='header'>
<p>ECharts 可视化分析淘宝双11</p>
</div>
<div class="content">
<div class="nav">
<ul>
<li><a href="./index.jsp">所有买家各消费行为对比</a></li>
<li><a href="./index1.jsp">男女买家交易对比</a></li>
<li><a href="./index2.jsp">男女买家各个年龄段交易对比</a></li>
<li><a href="./index3.jsp">商品类别交易额对比</a></li>
<li><a href="./index4.jsp">各省份的总成交量对比</a></li>
<li class="current"><a href="#">回头客预测分数对比</a></li>
</ul>
</div>
<div class="container">
<div class="title">回头客预测分数对比</div>
<div class="show">
<div class='chart-type'>极坐标柱状图</div>
<div id="main"></div>
</div>
</div>
</div>
<script>
// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 准备数据
var x = [];
var y = [];
<% for(Map.Entry<String, Integer> entry : scoreSegments.entrySet()) { %>
x.push('<%= entry.getKey() %>');
y.push(<%= entry.getValue() %>);
<% } %>
// 指定图表的配置项和数据
var option = {
backgroundColor: '#2c343c',
title: {
text: '回头客预测分数对比',
left: 'center',
top: 20,
textStyle: {
color: '#ccc'
}
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c}'
},
angleAxis: {
type: 'category',
data: x,
axisLine: {
lineStyle: {
color: '#ccc'
}
},
axisLabel: {
color: '#ccc'
}
},
radiusAxis: {
type: 'value',
axisLine: {
lineStyle: {
color: '#ccc'
}
},
axisLabel: {
color: '#ccc'
},
splitLine: {
lineStyle: {
color: '#aaa',
opacity: 0.3
}
}
},
polar: {},
series: [{
name: '人数',
type: 'bar',
data: y,
coordinateSystem: 'polar',
itemStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#83bff6'
}, {
offset: 0.5,
color: '#188df0'
}, {
offset: 1,
color: '#188df0'
}])
}
}]
};
// 使用刚指定的配置项和数据显示图表。
myChart.setOption(option);
</script>
</body>
</html>
3.步骤3
在其余index.jsp文件中此处(以index4.jsp处为例)
<li><a href="./index.jsp">所有买家各消费行为对比</a></li>
<li><a href="./index1.jsp">男女买家交易对比</a></li>
<li><a href="./index2.jsp">男女买家各个年龄段交易对比</a></li>
<li><a href="./index3.jsp">商品类别交易额对比</a></li>
<li class="current"><a href="#">各省份的总成交量对比</a></li>
添加代码,添加后的代码如下
<li><a href="./index.jsp">所有买家各消费行为对比</a></li>
<li><a href="./index1.jsp">男女买家交易对比</a></li>
<li><a href="./index2.jsp">男女买家各个年龄段交易对比</a></li>
<li><a href="./index3.jsp">商品类别交易额对比</a></li>
<li class="current"><a href="#">各省份的总成交量对比</a></li>
<li><a href="./index5.jsp">回头客预测分数对比</a></li>
4.结果图如下
5.回头客预测图数据分析
回头客的分数得分的分数是由之前的SVM算法得出来的,在这里将分数映射到了0—100区间,且将0—100分成了十段,每段中的大小表示在该段中有多少回头客,回头客的分数越高,说明偏离SVM划分的线越远,即回头购买物品的可能性越大。十段区间可以表示回头客回头的程度,可以进一步认为是客户的重要程度,90-100客户重要程度最大,90-80次之,以此类推,客户重要程度依次递减。以90-100为例,90-100段假设有200人,该段可以认为表示的意义为在所有回头客中有200个sssssssssvip回头客。
六、在其它设备打开可视化分析图
1.步骤1
将虚拟机网络连接方式改成:桥接网卡,如图所示(本人使用的是VM VirtualBox7.0)
2.步骤2
使用ifconfig命令查看虚拟机ip(红框里的部分)
确保虚拟机使用的网络与要打开可视化分析图设备的网络处于一个ip段,即查看ip的前三部分前缀应该相同
说人话就是连在一个wifi或热点下
3.步骤3
用其它设备打开http://<虚拟机的IP地址>:8080/MyWebApp 网址
把虚拟机的ip地址换成自己虚拟机的ip地址
之后就能打开了
参考链接:
淘宝双11数据分析与预测课程案例中(林子雨)错误点总结-CSDN博客
项目文档下载链接:
链接:https://pan.baidu.com/s/1ttF__sGXgZ1xAapkxUMEqA?pwd=k55r
提取码:k55r