可视化小白本学期一门课的作业报告,欢迎交流学习。
文章目录
一、 数据分析-WHAT
1. 属性数据
本可视化采用的是东方财富Choice数据提供的2019.09至2019.10中国电影单日票房数据,共有610项、6个属性。对属性的初步分析如下表所示。
属性 | 日期 | 排名 | 影片名 | 单日票房(万) | 环比变化(%) | 累计票房(万) |
---|---|---|---|---|---|---|
数据类型 | 日期,定距 | 数值,定序 | 字符串,定类 | 数值,定比 | 数值,定比 | 数值,定比 |
数量或范围 | 2019.9.1-2019.10.31 | - | 60部 | 7-37975 | - | 37-497280 |
备注 | - | - | - | 存在缺失上映期间某天数据的情况 | 同左 | 同左 |
2. 数据预处理
数据预处理包括两个方面:处理数据本身的问题、根据可视化工具(echarts)的输入数据格式对数据进行整理。
- 缺失值填补
单日票房、累计票房都存在上映期间某日数据缺失的情况。对于此类缺失值,单日票房填充0,累计票房用前一天的数据填充。 - 放映日期填充
echarts要求输入的类别数据与x轴标签等长。识别出数据集中每一部电影的上映日期和下映日期,将上映日期之前、下映日期之后的单日票房、累计票房都设置为特殊值(“-”),以便画图和查询时跳过。 - 标注影片首字母
使用pypinyin库获取影片首字母,以便可视化时将影片按首字母排序,便于查找。 - 数据格式转换
完成上述步骤后,将数据转化为json格式,定义为js文件(data.js)中的一个变量,以便调用。
二、 任务设计-WHY
1. 展示
每一部电影上映的时间段、上映期间单日票房变化。由于影片数量较多,在可视化时需要进行一定的分类、概括,否则会过于杂乱、无法识别。
2. 对比
同一电影不同日期的单日票房;
不同电影相同日期的单日票房;
电影市场单日总票房的变化情况;
不同电影的累计票房(不同电影累计票房的差异很大,需要添加缩放工具以便查看)。
3. 查询
根据电影名称查询单日票房。
4. 注释
注释周末、节假日(中秋节、国庆节),对比工作日与这些日期单日票房的差异。
三、 可视化设计-HOW
1. 视觉通道
- 用颜色表示影片。影片数量较多,视觉通道的容量较小,因此同时只用颜色标识少数几部影片,其他影片统一使用灰色表示,以突出重点。为了给每部电影生成一种固定的颜色,调用crc32算法对影片名称生成校验码,取结果中的六个字符作为十六进制颜色。
- 用位置(横坐标)表示日期。
- 用位置(折线图的纵坐标)表示累计票房。
- 用长度(堆叠面积图)表示单日票房。长度的堆叠体现了不同电影的单日票房组成了单日总票房的概念,此外还可以用堆叠图顶端的位置反映单日总票房信息。
2. 布局
左侧为影片名称展示区,按照影片首字母分组、排序;
右侧上图为单日票房堆叠图,下方为累计票房折线图。
3. 单日票房可视化
- 展示
使用堆叠图展示各影片的单日票房,便于用户感知当日电影市场总体情况、特定电影对当日电影市场的贡献、同一天不同电影的票房差异。 - 按影片名称筛选
因影片数量多,只显示用户指定的少数几部影片。在左侧电影列表中勾选选择要显示的影片,其他未被选中的影片的单日票房则累加作为“其他”类。
鼠标悬浮在图上时,在提示框中展示筛选出的影片当日的单日票房。
- 按日期缩放
拖动下方滑动条,可放大指定时间窗口内的单日票房情况。因堆叠图纵向缩放效果较差,堆叠图没有设置纵向缩放。
- 注释
在背景上用浅灰色标注了周末、节假日的范围,用文字注释了中秋节、国庆节对应的区域。
4. 累计票房可视化
- 展示
用折线图展示所有影片的累计票房随时间的变化。 - 按影片名称筛选
与单日票房面积堆叠图不同的是,所有电影的累计票房都被同时展示出来,区别在于在左侧电影列表中勾选的电影显示为彩色(与堆叠图中对应电影的颜色一致),其他电影显示为灰色。这一形式参考了课堂上介绍的一个可视化作品:
鼠标悬浮在折线图上的数据点上时,将显示该电影的名称、该日的累计票房(无论是否被选中,所有电影的累计票房都可按此方法查询)。
- 按日期、累计票房缩放
大部分影片的累计票房比热门影片低,在静态的折线图中难以辨识。通过横轴、纵轴的缩放可以更清晰地看到此类影片的累计票房。
四、 结果与发现
-
周末、节假日的单日票房明显高于工作日;
-
周末、节假日的前一天,单日票房就会开始有明显增长(如周五、9月30日);
-
周末、节假日的的单日票房在第一天达到最高点(除了10月12日);
-
中秋小长假、国庆假期单日票房远高于普通周末;
-
国庆档影片(9月28日-10月1日上映)的影片有8部,但国庆档的主要票房收入都被《我和我的祖国》、《中国机长》、《攀登者》瓜分。
-
9月-10月,上映以来累计票房超过10亿的影片共有6部:《哪吒之魔童降世》、《烈火英雄》、《速度与激情》、《我和我的祖国》、《中国机长》、《攀登者》。其中5部影片是国产电影,4部是正能量主旋律类型,3部在国庆档上映,可见观众们对讲好中国故事的影片非常欢迎,并且非常愿意通过看这类电影欢度国庆假期。
五、 思考
1. 信息取舍方面
面对类别多的定类数据,不能简单地全盘展示,需要进行一定的概括。
面对数值差异很大的定量数据,可以通过交互缩放的方式让用户选择要查看的区域,以展示细节。
2. 编程方面
这是我第一次使用前端技术进行可视化。同样是动态类型语言,在动态添加控件(元素)时Python和JavaScript有较大的不同。用PyQt动态添加控件时,需要实例化一个特定类型的对象,将对象添加到容器中;而JavaScript是直接添加字符串格式的一个或多个html元素,自由度非常高。
3. 不足
目前实现的交互查询主要是从影片名称查询影片票房、从累计票房图中查询影片名称,但用户可能有“查看某日热映影片”(即按单日票房排序)的需求,目前没有实现这种查询方式。
六、代码
piaofang.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>电影票房可视化</title>
<style>
h1 {
text-align: center;
}
.main {
height: 650px;
}
.subtitle {
font-weight:bold;
font-size:15px;
text-align:center;
height:10%;
}
.movie_name {
font-weight: normal;
padding: 0px 0px;
}
.letter {
font-weight: bold
}
.side_column {
float: left;
width: 22%;
height: 100%;
margin: 0 1%;
}
.movie_list {
float: left;
width: 100%;
height: 95%;
overflow-y:scroll; // 滚动条
}
.chart_list {
float: left;
width: 75%;
height: 100%;
}
</style>
<script src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/emn178/js-crc/build/crc.min.js"></script>
<script src="data.js"></script>
<script src="piaofang.js"></script>
</head>
<body>
<header>
<h1>中国电影票房(2019.09.01 ~ 2019.10.31)</h1>
</header>
<div class="main">
<div class="side_column">
<div style='font-weight:bold;font-size:15px;height:5%'>电影列表</div>
<div class="movie_list"></div>
</div>
<div class="chart_list">
<div style="height:50%;width:100%">
<div class="subtitle">单日票房(万元)</div>
<div id="box_per_day" style="height:90%;width:100%"></div>
</div>
<div style="height:49%;width:100%;padding:1% 0">
<div class="subtitle">累计票房(万元)</div>
<div id="box_sum" style="height:90%;width:100%"></div>
</div>
</div>
</div>
<script type="text/javascript">
// 生成字母分区
for (i = 0; i < 26; i++) {
let temp_div = '<div class="letter" id="letter_%x"><p>%x</p></div>';
temp_div = temp_div.replace(/%x/g, String.fromCharCode(65 + i));
$(".movie_list").append(temp_div);
}
// 生成checkbox
let selected = ["我和我的祖国", "中国机长", "罗小黑战记", "少年的你"]; // 默认选中的内容
for (i = 0; i < data.length; i++) {
let cb = '<div class="movie_name"><input type="checkbox" class="movie_checkbox" value="%x" %y>%x</div>';
if (selected.indexOf(data[i]["name"]) != -1) {
cb = cb.replace(/%y/g, 'checked');
}
cb = cb.replace(/%x/g, data[i]["name"]);
letter = data[i]["letter"];
$("#letter_" + letter).append(cb);
}
// 计算单日总票房
let day_sum = compute_day_sum(data)
// 单日总票房可视化
let myChart = echarts.init(document.getElementById('box_per_day'));
let options = box_day_options(selected, x_axis, data, day_sum);
myChart.setOption(options, true)
// 计算累积总票房
let box_sum_series = init_box_sum(data);
// 累积总票房可视化
let myChart2 = echarts.init(document.getElementById('box_sum'));
let options2 = box_all_options(selected, x_axis, box_sum_series);
myChart2.setOption(options2, true);
// 点击复选框事件
let checkboxes = document.getElementsByClassName('movie_checkbox');
$(".movie_checkbox").click(function () {
selected = [];
for (let i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked) {
selected.push(checkboxes[i].value);
}
}
options = box_day_options(selected, x_axis, data, day_sum);
myChart.setOption(options, true)
options2 = box_all_options(selected, x_axis, box_sum_series);
myChart2.setOption(options2, true)
});
</script>
</body>
</html>
data.js
let x_axis = ["2019-09-01", "2019-09-02", "2019-09-03", "2019-09-04", "2019-09-05", "2019-09-06", "2019-09-07", "2019-09-08", "2019-09-09", "2019-09-10", "2019-09-11", "2019-09-12", "2019-09-13", "2019-09-14", "2019-09-15", "2019-09-16", "2019-09-17", "2019-09-18", "2019-09-19", "2019-09-20", "2019-09-21", "2019-09-22", "2019-09-23", "2019-09-24", "2019-09-25", "2019-09-26", "2019-09-27", "2019-09-28", "2019-09-29", "2019-09-30", "2019-10-01", "2019-10-02", "2019-10-03", "2019-10-04", "2019-10-05", "2019-10-06", "2019-10-07", "2019-10-08", "2019-10-09", "2019-10-10", "2019-10-11", "2019-10-12", "2019-10-13", "2019-10-14", "2019-10-15", "2019-10-16", "2019-10-17", "2019-10-18", "2019-10-19", "2019-10-20", "2019-10-21", "2019-10-22", "2019-10-23", "2019-10-24", "2019-10-25", "2019-10-26", "2019-10-27", "2019-10-28", "2019-10-29", "2019-10-30", "2019-10-31"];
let data = [
{
"name": "\u6211\u548c\u6211\u7684\u7956\u56fd", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 1257.0, 0.0, 28660.0, 37975.0, 35858.0, 30248.0, 25809.0, 24315.0, 22271.0, 15798.0, 5296.0, 5420.0, 5389.0, 5044.0, 6957.0, 6426.0, 3228.0, 3220.0, 2972.0, 2775.0, 2237.0, 2022.0, 1527.0, 774.0, 1137.0, 1308.0, 1309.0, 1257.0, 1061.0, 921.0, 735.0, 803.0, 787.0, 961.0], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 1259.0, 1259.0, 29923.0, 67908.0, 103775.0, 134029.0, 159846.0, 184168.0, 206467.0, 222265.0, 227578.0, 233008.0, 238399.0, 243491.0, 250448.0, 256874.0, 260103.0, 263337.0, 266322.0, 269113.0, 271355.0, 273377.0, 274905.0, 275679.0, 276821.0, 278131.0, 279478.0, 280783.0, 281849.0, 282770.0, 283513.0, 284319.0, 285115.0, 286076.0], "letter": "W"},
{
"name": "\u4e2d\u56fd\u673a\u957f", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 5635.0, 0.0, 20704.0, 25607.0, 28232.0, 26724.0, 25273.0, 24462.0, 23527.0, 17542.0, 8200.0, 6923.0, 5948.0, 5895.0, 9087.0, 9811.0, 3313.0, 3263.0, 3095.0, 2859.0, 2667.0, 5117.0, 4018.0, 1549.0, 1560.0, 1456.0, 1358.0, 1244.0, 2240.0, 1809.0, 735.0, 720.0, 678.0, 598.0], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 5676.0, 5676.0, 26380.0, 52010.0, 80253.0, 106981.0, 132260.0, 156726.0, 180277.0, 197819.0, 206036.0, 212966.0, 218917.0, 224868.0, 233955.0, 243766.0, 247083.0, 250356.0, 253466.0, 256346.0, 259017.0, 264134.0, 268152.0, 269703.0, 271267.0, 272728.0, 274127.0, 275472.0, 277719.0, 279528.0, 280276.0, 281004.0, 281689.0, 282286.0], "letter": "Z"},
{
"name": "\u6500\u767b\u8005", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 4421.0, 0.0, 16721.0, 13632.0, 10648.0, 9024.0, 7720.0, 7257.0, 7298.0, 5630.0, 2530.0, 2245.0, 2022.0, 2028.0, 3178.0, 3588.0, 1387.0, 1033.0, 979.0, 938.0, 452.0, 861.0, 774.0, 348.0, 388.0, 377.0, 375.0, 218.0, 297.0, 254.0, 128.0, 150.0, 153.0, 137.0], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 4450.0, 4450.0, 21178.0, 34831.0, 45477.0, 54503.0, 62226.0, 69484.0, 76786.0, 82416.0, 84951.0, 87200.0, 89223.0, 91272.0, 94451.0, 98039.0, 99427.0, 100463.0, 101449.0, 102395.0, 102848.0, 103709.0, 104483.0, 104831.0, 105220.0, 105599.0, 105987.0, 106220.0, 106518.0, 106772.0, 106904.0, 107056.0, 107210.0, 107347.0], "letter": "P"},
{
"name": "\u5c11\u5e74\u7684\u4f60", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 14640.0, 23744.0, 19875.0, 8509.0, 7077.0, 5980.0, 5279.0], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 14640.0, 38391.0, 58266.0, 66781.0, 73868.0, 79855.0, 85135.0], "letter": "S"},
{
"name": "\u8bdb\u4ed9\u2160", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 14336.0, 8458.0, 4349.0, 1821.0, 1428.0, 1186.0, 997.0, 993.0, 1721.0, 1310.0, 516.0, 452.0, 417.0, 381.0, 477.0, 521.0, 719.0, 15.0, 0.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 14337.0, 22796.0, 27145.0, 28989.0, 30418.0, 31607.0, 32604.0, 33599.0, 35323.0, 36640.0, 37157.0, 37619.0, 38037.0, 38419.0, 38898.0, 39424.0, 40143.0, 40158.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "letter": "Z"},
{
"name": "\u6c89\u7761\u9b54\u54922", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 103.0, 3625.0, 6821.0, 5507.0, 2195.0, 2006.0, 1741.0, 1539.0, 1416.0, 2764.0, 1996.0, 639.0, 594.0, 560.0, 549.0], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 103.0, 3728.0, 10550.0, 16057.0, 18253.0, 20263.0, 22004.0, 23547.0, 24977.0, 27746.0, 29742.0, 30384.0, 30981.0, 31544.0, 32093.0], "letter": "C"},
{
"name": "\u901f\u5ea6\u4e0e\u6fc0\u60c5:\u7279\u522b\u884c\u52a8", "box_per_day": [5782.0, 2253.0, 1995.0, 1734.0, 1575.0, 1819.0, 3044.0, 2369.0, 963.0, 978.0, 845.0, 1012.0, 1458.0, 1328.0, 765.0, 336.0, 326.0, 307.0, 292.0, 236.0, 485.0, 384.0, 132.0, 129.0, 127.0, 126.0, 161.0, 0.0, 180.0, 0.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "box_sum": [117385.0, 119638.0, 121633.0, 123368.0, 124943.0, 126762.0, 129806.0, 132176.0, 133167.0, 134145.0, 134990.0, 136026.0, 137486.0, 138815.0, 139579.0, 139922.0, 140256.0, 140563.0, 140856.0, 141093.0, 141578.0, 141965.0, 142097.0, 142230.0, 142358.0, 142485.0, 142647.0, 142647.0, 143002.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "letter": "S"},
{
"name": "\u7f57\u5c0f\u9ed1\u6218\u8bb0", "box_per_day": ["-", "-", "-", "-", "-", 0.0, 4499.0, 3808.0, 1220.0, 1218.0, 1036.0, 1636.0, 3378.0, 3552.0, 2389.0, 597.0, 511.0, 459.0, 424.0, 492.0, 1498.0, 1320.0, 261.0, 237.0, 223.0, 207.0, 370.0, 654.0, 381.0, 23.0, 47.0, 83.0, 97.0, 103.0, 102.0, 94.0, 65.0, 12.0, 10.0, 12.0, 12.0, 0.0, 29.0, 0.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "box_sum": ["-", "-", "-", "-", "-", "-", 4719.0, 8530.0, 9752.0, 10970.0, 12006.0, 13658.0, 17037.0, 20590.0, 22978.0, 23586.0, 24098.0, 24558.0, 24983.0, 25475.0, 26974.0, 28298.0, 28559.0, 28801.0, 29024.0, 29232.0, 29604.0, 30258.0, 30639.0, 30662.0, 30713.0, 30798.0, 30895.0, 30998.0, 31100.0, 31194.0, 31259.0, 31271.0, 31282.0, 31294.0, 31307.0, 31307.0, 31345.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "letter": "L"},
{
"name": "\u54ea\u5412\u4e4b\u9b54\u7ae5\u964d\u4e16", "box_per_day": [3757.0, 1040.0, 921.0, 835.0, 771.0, 1076.0, 2536.0, 2131.0, 565.0, 590.0, 501.0, 783.0, 2231.0, 2471.0, 1464.0, 328.0, 295.0, 276.0, 269.0, 286.0, 1003.0, 900.0, 211.0, 200.0, 191.0, 179.0, 258.0, 481.0, 296.0, 19.0, 124.0, 249.0, 320.0, 355.0, 360.0, 331.0, 251.0, 30.0, 26.0, 26.0, 26.0, 27.0, 68.0, 8.0, 7.0, 0.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "box_sum": [471858.0, 472897.0, 473818.0, 474653.0, 475424.0, 476500.0, 479036.0, 481169.0, 481767.0, 482357.0, 482858.0, 483669.0, 485899.0, 488371.0, 489835.0, 490174.0, 490472.0, 490748.0, 491018.0, 491305.0, 492310.0, 493212.0, 493424.0, 493629.0, 493821.0, 494000.0, 494260.0, 494742.0, 495038.0, 495057.0, 495184.0, 495436.0, 495757.0, 496112.0, 496474.0, 496805.0, 497056.0, 497086.0, 497112.0, 497138.0, 497170.0, 497196.0, 497264.0, 497273.0, 497280.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "letter": "N"},
{
"name": "\u5c0f\u5c0f\u7684\u613f\u671b", "box_per_day": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 0.0, 3004.0, 5806.0, 3935.0, 2183.0, 929.0, 857.0, 769.0, 726.0, 844.0, 1741.0, 1366.0, 564.0, 559.0, 542.0, 495.0, 730.0, 800.0, 678.0, 0.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-"], "box_sum": ["-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", 3069.0, 8876.0, 12813.0, 14996.0, 15934.0, 16791.0, 17561.0, 18288.0, 19133.0, 20875.0, 22245.0, 22809.0, 23373.0, 23916.0, 24412.0, 25145.0, 25946.0, 26624.0, "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",