在上一部分《【python数据分析实战】电影票房数据分析(一)数据采集》 已经获取到了2011年至今的票房数据,并保存在了mysql中。

本文将在实操中讲解如何将mysql中的数据抽取出来并做成动态可视化。

图1 每年的月票房走势图

第一张图,我们要看一下每月的票房走势,毫无疑问要做成折线图,将近10年的票房数据放在一张图上展示。

数据抽取:

采集到的票房数据是按天统计的,并且我们只看正常上映的和点映的,其他如重映等场次均不在本次统计内。

因此我们先对mysql中的数据releaseInfo字段进行筛选,然后根据上映年份和月份进行分组聚合,得到10年内每月的票房数据。

用sql取到数据后,再将不同年份的数据分别放入list中,原始数据是以"万"为单位的str,这里我们折算为以"亿"为单位的float。

构造图像:

x轴数据为年份,

再分别将不同年份的票房数据添加到y轴中,

最后配置下图像的属性即可。

config = {...}    # db配置省略
conn = pymysql.connect(**config)
cursor = conn.cursor()
sql = '''
select substr(`date`,1,4) year,
substr(`date`,5,2) month,
round(sum(`boxInfo`),2) monthbox
from movies_data
where (substr(`releaseInfo`,1,2) = '上映' or `releaseInfo`='点映' )
group by year,month order by year,month
'''
cursor.execute(sql)
data = cursor.fetchall()
x_data = list(set([int(i[1]) for i in data]))
x_data.sort()
x_data = list(map(str, x_data))
y_data1 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2011']
y_data2 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2012']
y_data3 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2013']
y_data4 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2014']
y_data5 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2015']
y_data6 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2016']
y_data7 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2017']
y_data8 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2018']
y_data9 = [round(int(i[2]) / 10000, 2) for i in data if i[0] == '2019']
cursor.close()
conn.close() def line_base() -> Line:
c = (
Line(init_opts=opts.InitOpts(height="600px", width="1300px"))
.add_xaxis(x_data)
.add_yaxis("2011", y_data1)
.add_yaxis("2012", y_data2)
.add_yaxis("2013", y_data3)
.add_yaxis("2014", y_data4)
.add_yaxis("2015", y_data5)
.add_yaxis("2016", y_data6)
.add_yaxis("2017", y_data7)
.add_yaxis("2018", y_data8)
.add_yaxis("2019", y_data9)
.set_global_opts(title_opts=opts.TitleOpts(title="月票房走势"),
legend_opts=opts.LegendOpts(
type_="scroll", pos_top="55%", pos_left="95%", orient="vertical"),
xaxis_opts=opts.AxisOpts(
axistick_opts=opts.AxisTickOpts(is_align_with_label=True), boundary_gap=False, ),)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False), # 不显示柱体上的标注(数值)
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(type_="max", name="最大值"), ]), )
.extend_axis(yaxis=opts.AxisOpts(name="票房(亿元)", position='left'), # 设置y轴标签显示格式,数据+"人"
xaxis=opts.AxisOpts(name="月份"))
) return c line_base().render("v1.html")

有本图可以看出:

1、近10年票房总数逐渐增长(当然这是废话)

2、11-13年每月票房波动很小,几乎没有明显的高峰档期,最近两年高峰档期最为明显,集中在春节、暑期和十一。

图2 年票房总值、上映影片总数及观影人次

第二张图,我们要看一下票房、上映影片数和观影人次 逐年的变化情况

数据抽取:

先筛选releaseInfo 为正常上映和首映的数据,

再按年份分组,也就是date字段的前4位,

  • 对当日票房字段进行sum聚合得到年度总票房;
  • 对movieId字段去重 并求得出现次数 即为上映的影片总数;
  • 场均人数 * 排片场次 是当日观影人次,再用sum求得年观影人次。

构造图像:

因为三类数据的x轴都是年份,所以可放在一张图上展示,为了观察更直观,将其中一项数据作成柱状图,另外两项做成折线图。

  • 1、先构造折线图图,将票房和影片数量添加为y轴数据,年份为x轴数据。
  • 2、因为票房和上映影片数 在做完单位换算后,值域基本相同,所以可以共用一个y轴,而观影人次则需要使用单独的y轴,

    所以要添加一个新的y轴,并分别指定这三项数据的y轴索引,即票房和上映影片数 使用默认的y轴索 引为0,而观影人次使用后添加的y轴,索引为1。
  • 3、再构造柱状图,y轴数据为观影人次,x轴数据依然为年份,并指定y轴索引为1
  • 4、最后,将柱状图和折线图重叠输出,再简单调整一下图像位置即可。
config = {...}    # db配置省略
conn = pymysql.connect(**config)
cursor = conn.cursor()
sql2 = '''select substr(date,1,4),
round(sum(boxInfo)/10000,2),
count(DISTINCT movieId),
round(sum(avgShowView*showInfo)/100000000,2)
from movies_data
where (substr(`releaseInfo`,1,2) = '上映' or `releaseInfo`='点映' )
GROUP by substr(date,1,4)'''
cursor.execute(sql2)
data2 = cursor.fetchall()
x_data2 = [i[0] for i in data2]
y_data2_1 = [i[1] for i in data2]
y_data2_2 = [i[2] for i in data2]
y_data2_3 = [i[3] for i in data2]
cursor.close()
conn.close() def bar_base() -> Line:
c = (
Line()
.add_xaxis(x_data2)
.add_yaxis("总票房", y_data2_1, yaxis_index=0)
.add_yaxis("上映电影总数", y_data2_2, color='LimeGreen', yaxis_index=0, )
.set_global_opts(title_opts=opts.TitleOpts(title="年票房总值、上映影片总数及观影总人次"),
legend_opts=opts.LegendOpts(pos_left="40%"),
)
.extend_axis(
yaxis=opts.AxisOpts(name="票房/数量(亿元/部)", position='left'))
.extend_axis(
yaxis=opts.AxisOpts(name="人次(亿)", type_="value", position="right", # 设置y轴的名称,类型,位置
axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color="#483D8B")), ))
) bar = (
Bar()
.add_xaxis(x_data2)
.add_yaxis("观影人次", y_data2_3, yaxis_index=2, category_gap="1%",
label_opts=opts.LabelOpts(position="inside")) ) c.overlap(bar)
return Grid().add(c, opts.GridOpts(pos_left="10%",pos_top='20%'), is_control_axis_index=True) # 调整位置 bar_base().render("v2.html")

本图可以看出:

(2019年数据下滑是因为统计时 2019年刚到10月下旬,还没有得到一年完整的数据。)

1、上映影片数增长幅度不大,票房和观影人次涨幅相近,因此票房逐年增长的最主要原因是观影人次的增长,年平均票价应该变化不大。

图3 单片总票房及日均票房

影片的上映期长短不一,这也影响了影片的票房情况,所以这张图我们要看一下单片总票房和日均票房的情况。

config = {...}    # db配置省略
conn = pymysql.connect(**config) cursor = conn.cursor()
sql2 = '''select a.*,b.releasemonth from
(select movieid,
moviename,
round(sum(boxinfo)/10000,2) sumBox,
count(movieid) releasedays,
round(sum(boxinfo)/count(movieid)/10000,2) avgdaybox
from movies_data
where (substr(`releaseInfo`,1,2) = '上映' or `releaseInfo`='点映' )
group by movieid,moviename) a ,
(select substr(date,5,2) releasemonth,movieId,movieName,releaseInfo from movies_data where releaseInfo='上映首日') b
where a.movieid = b.movieid order by sumBox desc'''
cursor.execute(sql2)
data3 = cursor.fetchall()
x_data3 = [i[1] for i in data3[:30]] # 名称
y_data3_1 = [i[2] for i in data3[:30]] # 总票房
y_data3_2 = [i[4] for i in data3[:30]] # 日均票房
y_data3_3 = [int(i[5]) for i in data3[:30]] # 上映月份
cursor.close()
conn.close() def bar_base() -> Line:
c = (
Bar(init_opts=opts.InitOpts(height="600px", width="1500px"))
.add_xaxis(x_data3)
.add_yaxis("影片总票房", y_data3_1, yaxis_index=0)
# .add_yaxis("影片日均票房", y_data3_2, yaxis_index=1, gap='-40%')
.set_global_opts(title_opts=opts.TitleOpts(title="单片总票房及日均票房"),
xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-45)),
datazoom_opts=opts.DataZoomOpts(), )
.set_series_opts(label_opts=opts.LabelOpts(is_show=False), # 不显示柱体上的标注(数值)
markpoint_opts=opts.MarkPointOpts(
data=[opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"), ]),)
.extend_axis(
yaxis=opts.AxisOpts(name="亿元", position='left'))
.extend_axis(
yaxis=opts.AxisOpts(name="亿元", type_="value", position="right", # 设置y轴的名称,类型,位置
axisline_opts=opts.AxisLineOpts(linestyle_opts=opts.LineStyleOpts(color="#483D8B")), ))
) bar = (
Bar(init_opts=opts.InitOpts(height="600px", width="1500px"))
.add_xaxis(x_data3)
# .add_yaxis("影片总票房", y_data3_1, yaxis_index=0)
.add_yaxis("影片日均票房", y_data3_2, yaxis_index=2, gap='-40%')
.set_global_opts(title_opts=opts.TitleOpts(title="单片总票房及日均票房"),)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False), # 不显示柱体上的标注(数值)
markpoint_opts=opts.MarkPointOpts(
data=[opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"), ]),
markline_opts=opts.MarkLineOpts(
data=[opts.MarkLineItem(type_="average", name="平均值"), ]
),) ) c.overlap(bar)
return Grid().add(c, opts.GridOpts(pos_left="5%", pos_right="20%"), is_control_axis_index=True) # 调整位置 bar_base().render("v3.html")

可以看出有的电影虽然总票房一般,但是日均票房很高,说明上映时间不长但却很火爆。

而对于总票房很高,但日均票房一般的影片,可能是由于上映时间较长,后期较低的上座率拉低了日均票房。

所以看一个影片的火爆程度,总票房只是一方面,在相同上映时间内的上座率变化趋势也很重要。

图4 单片票房及上映月份关系图

本图相当于图一的补充,主要是看一下高票房的影片和上映时间的关系


def dayformat(i):
mm = int(i[-2])
dd = int(i[-1])
mmdd = mm + dd/100*3.3
return mmdd config = {...} # db配置省略
conn = pymysql.connect(**config) cursor = conn.cursor()
sql2 = '''select a.*,b.releaseyear,b.releasemonth,b.releaseday from
(select movieid,
moviename,
round(sum(boxinfo)/10000,2) sumBox,
count(movieid) releasedays,
round(sum(boxinfo)/count(movieid)/10000,2) avgdaybox
from movies_data
where (substr(`releaseInfo`,1,2) = '上映' or `releaseInfo`='点映' )
group by movieid,moviename) a ,
(select substr(date,1,4) releaseyear,
substr(date,5,2) releasemonth,
substr(date,7,2) releaseday,
movieId,
movieName,
releaseInfo
from movies_data where releaseInfo='上映首日') b
where a.movieid = b.movieid order by sumBox desc''' cursor.execute(sql2)
data4 = cursor.fetchall() x_data4 = [i for i in range(1, 13)]
y_data4_1 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2011']
y_data4_2 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2012']
y_data4_3 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2013']
y_data4_4 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2014']
y_data4_5 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2015']
y_data4_6 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2016']
y_data4_7 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2017']
y_data4_8 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2018']
y_data4_9 = [(dayformat(i), i[2]) for i in data4 if i[-3] == '2019']
cursor.close()
conn.close() my_config = pygal.Config() # 创建Config实例
my_config.show_y_guides = False # 隐藏水平虚线
my_config.show_x_guides = True
xy_chart = pygal.XY(stroke=False, config=my_config)
xy_chart.title = '单片票房及上映月份关系图' xy_chart.add('2011', y_data4_1)
xy_chart.add('2012', y_data4_2)
xy_chart.add('2013', y_data4_3)
xy_chart.add('2014', y_data4_4)
xy_chart.add('2015', y_data4_5)
xy_chart.add('2016', y_data4_6)
xy_chart.add('2017', y_data4_7)
xy_chart.add('2018', y_data4_8)
xy_chart.add('2019', y_data4_9) xy_chart.render_to_file("v4.svg")

上一部分《【python数据分析实战】电影票房数据分析(一)数据采集》

【python数据分析实战】电影票房数据分析(二)数据可视化的更多相关文章

  1. Python数据分析实战:使用pyecharts进行数据可视化

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:刘早起 开始使用 基本套路就是先创建一个你需要的空图层,然后使用.s ...

  2. 【python数据分析实战】电影票房数据分析(一)数据采集

    目录 1.获取url 2.开始采集 3.存入mysql 本文是爬虫及可视化的练习项目,目标是爬取猫眼票房的全部数据并做可视化分析. 1.获取url 我们先打开猫眼票房http://piaofang.m ...

  3. python实现的电影票房数据可视化

    代码地址如下:http://www.demodashi.com/demo/14275.html 详细说明: Tushare是一个免费.开源的python财经数据接口包.主要实现对股票等金融数据从数据采 ...

  4. python pandas 豆瓣电影 top250 数据分析

    豆瓣电影top250数据分析 数据来源(豆瓣电影top250) 爬虫代码比较简单 数据较为真实,可以进行初步的数据分析 可以将前面的几篇文章中的介绍的数据预处理的方法进行实践 最后用matplotli ...

  5. Spark实战电影点评系统(二)

    二.通过DataFrame实战电影点评系统 DataFrameAPI是从Spark 1.3开始就有的,它是一种以RDD为基础的分布式无类型数据集,它的出现大幅度降低了普通Spark用户的学习门槛. D ...

  6. 详解Python Streamlit框架,用于构建精美数据可视化web app,练习做个垃圾分类app

    今天详解一个 Python 库 Streamlit,它可以为机器学习和数据分析构建 web app.它的优势是入门容易.纯 Python 编码.开发效率高.UI精美. 上图是用 Streamlit 构 ...

  7. python爬虫: 豆瓣电影top250数据分析

    转载博客 https://segmentfault.com/a/1190000005920679 根据自己的环境修改并配置mysql数据库 系统:Mac OS X 10.11 python 2.7 m ...

  8. [读书笔记] Python 数据分析 (八)画图和数据可视化

    ipython3 --pyplot pyplot: matplotlib 画图的交互使用环境

  9. SPSSAU数据分析思维培养系列4:数据可视化篇

    本文章为SPSSAU数据分析思维培养的第4期文章. 前3期内容分别讲述数据思维,分析方法和分析思路.本文讲述如何快速使用SPSSAU进行高质量作图,以及如何选择使用正确的图形. 本文分别从五个角度进行 ...

随机推荐

  1. nginx重启失败,无法关闭nginx占用端口

    nginx配置修改后,需要重启nginx,出现上图中的异常. 找不见无法正常nginx的原因,所以只能强制关闭所有端口,再重启nginx 运行命令:fuser -k 80/tcp

  2. Mybatis源码解析,一步一步从浅入深(六):映射代理类的获取

    在文章:Mybatis源码解析,一步一步从浅入深(二):按步骤解析源码中我们提到了两个问题: 1,为什么在以前的代码流程中从来没有addMapper,而这里却有getMapper? 2,UserDao ...

  3. spring web 脚手架 (持续更新中...)

    spring web 脚手架 项目地址: https://github.com/MengW9/scafflod.git 还有觉得哪些可以加上去的配置,欢迎各位拍砖,我会持续更新,大家共同进步 一个通用 ...

  4. 一步步构建.NET Core Web应用程序---基本项目结构

    前言 随着.NET Core日益成熟, 我作为C#&.NET体系中的一份子也加入了.NET Core 这一体系中,随着不断学习, 接触到的各种框架日益庞杂,接下来我会由一个新手的角度把整个基于 ...

  5. Redis数据库之服务器主从配置

    目的 主要培养对分布式REDIS主从复制架构运用的能力.理解并掌握REPLICATION工作原理的同时,能独立配置Replication ,使数据库运行在主从架格上.针对主从复制架构的运用,着力掌握S ...

  6. 基于操作系统的Linux网络参数的配置

    一.实验目的 1.掌握Linux下网络参数的查看方法并理解网络参数的含义. 2.掌握Linux下网络参数的配置 二.实验内容 1.查看当前网络配置的参数. 2.在Linux主机中将网络参数按以下要求设 ...

  7. 前端基于VUE的v-charts的曲线显示

    目录 前端基于VUE的v-charts的曲线显示 1. 应用背景 2. 分析数据生产者生成 3. 取出数据消费者 4. 前端显示 4.1 安装V-charts插件 4.2 引入veline曲线插件 4 ...

  8. python爬取哦漫画

    import requests from lxml import etree from bs4 import BeautifulSoup import os from selenium import ...

  9. 虚拟机中设置 CentOS 静态 IP

    作为开发人员在工作和学习中通过虚拟机使用 Linux 的情况肯定会非常多,但是 Linux 自带的终端使用体验较差,所以绝大多数使用者都会在宿主机上使用第三方 SSH工具(例如 Xshell)进行连接 ...

  10. MySQL 复制已存在的表生成新表

    从已有的表创建一个新的空表 CREATE TABLE new_table LIKE old_table; 注意: create table ... like 创建的表会保留原有表的字段.索引的定义,但 ...