• 【拖拽可视化大屏】全流程讲解用python的pyecharts库实现拖拽可视化大屏的背后原理,简单粗暴!


    “整篇文章较长,干货很多!建议收藏后,分章节阅读。”

    一、设计方案

    整体设计方案思维导图:

    整篇文章,也将按照这个结构来讲解。

    若有重点关注部分,可点击章节目录直接跳转!

    二、项目背景

    针对TOP250排行榜的数据,开发一套可视化数据大屏系统,展示各维度数据分析结果。
    TOP250排行榜

    三、电影爬虫

    3.1 导入库

    import requests  # 发送请求
    from bs4 import BeautifulSoup  # 解析网页
    import pandas as pd  # 存取csv
    from time import sleep  # 等待时间
    from sqlalchemy import create_engine  # 连接数据库
    

    3.2 发送请求

    定义一些空列表,用于临时存储爬取下的数据:

    movie_name = []  # 电影名称
    movie_url = []  # 电影链接
    movie_star = []  # 电影评分
    movie_star_people = []  # 评分人数
    movie_director = []  # 导演
    movie_actor = []  # 主演
    movie_year = []  # 上映年份
    movie_country = []  # 国家
    movie_type = []  # 类型
    short_comment = []  # 一句话短评
    

    向网页发送请求:

    res = requests.get(url, headers=headers)
    

    3.3 解析页面

    利用BeautifulSoup库解析响应页面:

    soup = BeautifulSoup(res.text, 'html.parser')
    

    用BeautifulSoup的select函数,(css解析的方法)编写代码逻辑,部分核心代码:

    for movie in soup.select('.item'):
    	name = movie.select('.hd a')[0].text.replace('\n', '')  # 电影名称
    	movie_name.append(name)
    	url = movie.select('.hd a')[0]['href']  # 电影链接
    	movie_url.append(url)
    	star = movie.select('.rating_num')[0].text  # 电影评分
    	movie_star.append(star)
    	star_people = movie.select('.star span')[3].text  # 评分人数
    	star_people = star_people.strip().replace('人评价', '')
    

    其中,需要说明的是,《大闹天宫》这部电影和其他电影页面排版不同:

    所以,这里特殊处理一下:

    if name == '大闹天宫 / 大闹天宫 上下集  /  The Monkey King':  # 大闹天宫,特殊处理
    	year0 = movie_infos.split('\n')[1].split('/')[0].strip()
    	year1 = movie_infos.split('\n')[1].split('/')[1].strip()
    	year2 = movie_infos.split('\n')[1].split('/')[2].strip()
    	year = year0 + '/' + year1 + '/' + year2
    	movie_year.append(year)
    	country = movie_infos.split('\n')[1].split('/')[3].strip()
    	movie_country.append(country)
    	type = movie_infos.split('\n')[1].split('/')[4].strip()
    	movie_type.append(type)
    

    3.4 存储到csv

    最后,将爬取到的数据保存到csv文件中:

    def save_to_csv(csv_name):
    	"""
    	数据保存到csv
    	:return: None
    	"""
    	df = pd.DataFrame()  # 初始化一个DataFrame对象
    	df['电影名称'] = movie_name
    	df['电影链接'] = movie_url
    	df['电影评分'] = movie_star
    	df['评分人数'] = movie_star_people
    	df['导演'] = movie_director
    	df['主演'] = movie_actor
    	df['上映年份'] = movie_year
    	df['国家'] = movie_country
    	df['类型'] = movie_type
    	df.to_csv(csv_name, encoding='utf_8_sig')  # 将数据保存到csv文件
    

    其中,把各个list赋值为DataFrame的各个列,就把list数据转换为了DataFrame数据,然后直接to_csv保存。

    3.5 讲解视频

    同步讲解视频:
    https://www.zhihu.com/zvideo/1465578220191592448

    四、数据持久化存储

    然后,就可以把csv数据导入到MySQL数据库,做持久化存储了。

    4.1 导入库

    import pandas as pd  # 存取csv
    from sqlalchemy import create_engine  # 连接数据库
    

    4.2 存入MySQL

    最核心的三行代码:

    # 把csv导入mysql数据库
    engine = create_engine('mysql+pymysql://root:123456@localhost/db_bigscreen')
    df = pd.read_csv('Movie250.csv')
    df.to_sql(name='t_film', con=engine, chunksize=1000, if_exists='replace', index=None)
    

    用create_engine创建数据库连接,格式为:

    create_engine('数据库类型+数据库驱动://用户名:密码@数据库IP地址/数据库名称')

    这样,数据库连接就创建好了。

    然后,用pandas的read_csv函数读取csv文件。

    最后,用pandas的to_sql函数,把数据存入MySQL数据库:

    name='college_t2' #mysql数据库中的表名
    con=engine # 数据库连接
    index=False #不包含索引字段
    if_exists='replace' #如果表中存在数据,就替换掉,另外,还支持append(追加数据)
    非常方便地完成了反向导入,即:从csv向数据库的导入。

    4.3 讲解视频

    同步讲解视频:
    https://www.zhihu.com/zvideo/1496218294043009024

    五、开发可视化大屏

    如文章开头的思维导图所说,首先把各个子图表开发出来,然后用pyecharts的Page组件,把这些子图表拼装组合起来,形成大屏。

    下面,依次讲解每个子图表的实现。

    5.1 柱形图

    pyecharts官网-柱形图:A Python Echarts Plotting Library built with love.

    因为需要实现分段区间统计,所以先定义出一个区间对象:

    # 设置分段
    bins = [0, 100000, 200000, 300000, 500000, 1000000, 3000000]
    # 设置标签
    labels = ['0-10w', '10w-20w', '20w-30w', '30w-50w', '50w-100w', '100w-300w']
    

    然后,对数据进行按段切割,并统计个数:

    # 按分段离散化数据
    segments = pd.cut(cmt_count_list, bins, labels=labels)  # 按分段切割数据
    counts = pd.value_counts(segments, sort=False).values.tolist()  # 统计个数
    

    最后,采用pyecharts里的Bar对象,画出柱形图:

    bar = Bar(
    	init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='bar_cmt2'))  # 初始化条形图
    bar.add_xaxis(labels, )  # 增加x轴数据
    bar.add_yaxis("评价数", counts)  # 增加y轴数据
    bar.set_global_opts(
    	legend_opts=opts.LegendOpts(pos_left='right'),
    	title_opts=opts.TitleOpts(title="评价数量区间分布-柱形图", pos_left='center'),  # 标题
    	toolbox_opts=opts.ToolboxOpts(is_show=False, ),  # 不显示工具箱
    	xaxis_opts=opts.AxisOpts(name="评论数",  # x轴名称
    	                         axislabel_opts=opts.LabelOpts(font_size=8)),  # 字体大小
    	yaxis_opts=opts.AxisOpts(name="电影数量",
    	                         axislabel_opts={"rotate": 0},
    	                         splitline_opts=opts.SplitLineOpts(is_show=True,
    	                                                           linestyle_opts=opts.LineStyleOpts(type_='solid')),
    	                         ),  # y轴名称
    )
    # 标记最大值
    bar.set_series_opts(
    	markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max", name="最大值"), ],
    	                                  symbol_size=35)  # 标记符号大小
    )
    bar.render("评价数分布-柱形图.html")  # 生成html文件
    print('生成完毕:评价数分布-柱形图.html')
    

    图表效果:

    5.2 饼图

    pyecharts官网-饼图:A Python Echarts Plotting Library built with love.

    绘制情感分布的饼图。所以,首先要对评价数据进行情感分析。

    鉴于电影评价内容都是中文文本设计,情感分析采用snownlp技术进行。

    score_list = []  # 情感评分值
    tag_list = []  # 打标分类结果
    pos_count = 0  # 计数器-积极
    mid_count = 0  # 计数器-中性
    neg_count = 0  # 计数器-消极
    for comment in v_cmt_list:
    	tag = ''
    	sentiments_score = SnowNLP(comment).sentiments
    	if sentiments_score < 0.4:  # 情感分小于0.4判定为消极
    		tag = '消极'
    		neg_count += 1
    	elif 0.4 <= sentiments_score <= 0.6:  # 情感分在[0.4,0.6]直接判定为中性
    		tag = '中性'
    		mid_count += 1
    	else:  # 情感分大于0.6判定为积极
    		tag = '积极'
    		pos_count += 1
    	score_list.append(sentiments_score)  # 得分值
    	tag_list.append(tag)  # 判定结果
    df['情感得分'] = score_list
    df['分析结果'] = tag_list
    df.to_excel('情感判定结果.xlsx', index=None)  # 把情感分析结果保存到excel文件
    

    按照情感得分值划分区间:

    情感得分值小于0.4,判定为消极
    情感得分值在0.4与0.6之间,判定为中性
    情感得分值大于0.6,判定为积极

    最终将结果保存到Excel文件中,查看下:

    将此结果中的数据,带入到Pie组件中,画出饼图:

    # 画饼图
    pie = (
    	Pie(init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='pie1'))
    		.add(series_name="评价情感分布",  # 系列名称
    	         data_pair=[['积极', pos_count],  # 添加数据
    	                    ['中性', mid_count],
    	                    ['消极', neg_count]],
    	         rosetype="radius",  # 是否展示成南丁格尔图
    	         radius=["30%", "55%"],  # 扇区圆心角展现数据的百分比,半径展现数据的大小
    	         )  # 加入数据
    		.set_global_opts(  # 全局设置项
    		title_opts=opts.TitleOpts(title="短评情感分布-饼图", pos_left='center'),  # 标题
    		legend_opts=opts.LegendOpts(pos_left='right', orient='vertical')  # 图例设置项,靠右,竖向排列
    	)
    		.set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")))  # 样式设置项
    pie.render('情感分布_饼图.html')  # 生成html文件
    print('生成完毕:情感分布_饼图.html')
    

    图表效果:

    5.3 词云图

    pyecharts官网-词云图:A Python Echarts Plotting Library built with love.

    针对TOP250的电影名称,绘制出词云图。

    先对数据做清洗操作,然后直接画出词云图即可:

    wc = WordCloud(init_opts=opts.InitOpts(width="450px", height="350px", theme=theme_config, chart_id='wc1'))
    wc.add(series_name="电影名称",
           data_pair=data,
           word_size_range=[15, 20],
           width='400px',  # 宽度
           height='300px',  # 高度
           word_gap=5  # 单词间隔
           )  # 增加数据
    wc.set_global_opts(
    	title_opts=opts.TitleOpts(pos_left='center',
    	                          title="电影名称分析-词云图",
    	                          title_textstyle_opts=opts.TextStyleOpts(font_size=20)  # 设置标题
    	                          ),
    	tooltip_opts=opts.TooltipOpts(is_show=True),  # 不显示工具箱
    )
    wc.set_series_opts(label_opts=opts.LabelOpts(is_show=True))
    wc.render('电影名称_词云图.html')  # 生成html文件
    print('生成完毕:电影名称_词云图.html')
    

    图表效果:

    5.4 数据表格

    pyecharts官网-表格:A Python Echarts Plotting Library built with love.

    把排名前10的电影详情数据,展现到大屏上,采用pyecharts里的Table组件实现。

    从MySQL数据库读取到数据后,直接进行绘制表格:

    table = (
    	Table(page_title='我的表格标题', )
    		.add(headers=['排名', '电影名称', '评分', '评论数', '上映年', '一句话短评'], rows=data_list, attributes={
    		"align": "left",
    		"border": False,
    		"padding": "20px",
    		"style": "background:{}; width:450px; height:350px; font-size:10px; color:#C0C0C0;padding:3px;".format(
    			table_color)
    	})
    		.set_global_opts(title_opts=opts.TitleOpts(title='这是表格1'))
    )
    table.render('电影排名TOP10_数据表格.html')
    print('生成完毕:电影排名TOP10_数据表格.html')
    

    图表效果:

    5.5 涟漪散点图

    pyecharts官网-涟漪散点图:A Python Echarts Plotting Library built with love.

    针对电影的上映年份和评分值,两个纬度的数据,绘制出涟漪散点图(涟漪散点图和普通散点图的区别,就是涟漪散点图是动态图,图上的每个点都在闪烁,像水面上的涟漪一样)。

    sc = (EffectScatter(init_opts=opts.InitOpts(width="450px", height="350px", theme=theme_config, chart_id='scatter1'))
          .add_xaxis(xaxis_data=x_data)
          .add_yaxis(
    	series_name="",
    	y_axis=y_data,
    	symbol_size=10,
    	label_opts=opts.LabelOpts(is_show=False),
    )
          .set_series_opts()
          .set_global_opts(
          		# 忽略部分代码
                           )
          )
    sc.render('评分年份分布-散点图.html')
    print('生成完毕:散点图.html')
    

    图表效果:

    5.6 条形图

    pyecharts官网-条形图:A Python Echarts Plotting Library built with love.

    针对评论数最多的10个电影名称,绘制出横向条形图。

    # 画条形图
    bar = Bar(
    	init_opts=opts.InitOpts(theme=theme_config, width="450px", height="350px", chart_id='bar_cmt1'))  # 初始化条形图
    bar.add_xaxis(x_data)  # 增加x轴数据
    bar.add_yaxis("评论数量", y_data)  # 增加y轴数据
    bar.reversal_axis()  # 设置水平方向
    bar.set_series_opts(label_opts=opts.LabelOpts(position="right"))  # Label出现位置
    bar.set_global_opts(
    	legend_opts=opts.LegendOpts(pos_left='right'),
    	title_opts=opts.TitleOpts(title="评论数TOP10作者-条形图", pos_left='center'),  # 标题
    	toolbox_opts=opts.ToolboxOpts(is_show=False, ),  # 不显示工具箱
    	xaxis_opts=opts.AxisOpts(name="评论",  # x轴名称
    	                         axislabel_opts=opts.LabelOpts(font_size=8, rotate=0),
    	                         splitline_opts=opts.SplitLineOpts(is_show=False)
    	                         ),
    	yaxis_opts=opts.AxisOpts(name="电影",  # y轴名称
    	                         axislabel_opts=opts.LabelOpts(font_size=7, rotate=45),  # y轴名称
    	                         )
    )
    bar.render("评论数TOP10_条形图.html")  # 生成html文件
    print('生成完毕:评论数TOP10_条形图.html')
    

    图表效果:

    5.7 大标题

    由于pyecharts组件没有专门用作标题的图表,我决定灵活运用Table组件实现大标题。即,让Table只有标题header,没有数据行row,再针对header做一些样式调整(字体增大等),即可实现一行大标题。

    table = Table()
    table.add(headers=[v_title], rows=[], attributes={
    	"align": "center",
    	"border": False,
    	"padding": "2px",
    	"style": "background:{}; width:1350px; height:50px; font-size:25px; color:#C0C0C0;".format(table_color)
    })
    table.render('大标题.html')
    print('生成完毕:大标题.html')
    

    图表效果:

    5.8 Page组合

    最后,也是最关键的一步,把以上所有图表组合到一起,用Page组件,并且选用DraggablePageLayout方法,即拖拽的方式,组合图表:

    # 绘制:整个页面
    page = Page(
    	page_title="基于Python的电影数据分析大屏",
    	layout=Page.DraggablePageLayout,  # 拖拽方式
    )
    page.add(
    	# 增加:大标题
    	make_title(v_title='基于Python的电影数据分析大屏'),
    	# 绘制:中下方数据表格
    	make_table(v_df=df_table),
    	# 绘制:电影名称词云图
    	filmname_wordcloud(v_str=film_all_list),
    	# 绘制:TOP10评论数-条形图
    	make_top10_comment_bar(v_df=df),
    	# 绘制情感分布饼图
    	make_analyse_pie(v_cmt_list=comment_all_list),
    	# 绘制:评价数分段统计-柱形图
    	make_cmt_count_bar(v_df=df),
    	# 绘制:散点图
    	make_scatter(x_data=year_list, y_data=score_list)
    )
    page.render('大屏_临时.html')  # 执行完毕后,打开临时html并排版,排版完点击Save Config,把json文件放到本目录下
    print('生成完毕:大屏_临时.html')
    

    本代码执行完毕后,打开临时html并排版,排版完点击SaveConfig,把json文件放到本目录下。

    再执行最后一步,调用json配置文件,生成最终大屏文件。

    # 执行之前,请确保:1、已经把json文件放到本目录下 2、把json中的title和table的id替换掉
    Page.save_resize_html(
    	source="大屏_临时.html",
    	cfg_file="chart_config.json",
    	dest="大屏_最终_0426.html"
    )
    

    拖拽过程的演示视频:
    https://www.zhihu.com/zvideo/1502249430140616704

    至此,所有代码执行完毕,生成了最终大屏html文件。

    六、彩蛋-多种主题

    为了实现不同颜色主题的大屏可视化效果,我开发了一个实现逻辑,只需修改一个参数,即可展示不同颜色主题。

    全局设置主题颜色

    theme_config = ThemeType.CHALK # 颜色方案
    由于Table组件是不能设置颜色主题的,所以我手写了一个逻辑(用取色器获取的RGB值,又转成十六进制的颜色!),如下:

    # 表格和标题的颜色
    table_color = ""
    if theme_config == ThemeType.DARK:
    	table_color = '#333333'
    elif theme_config == ThemeType.CHALK:
    	table_color = '#293441'
    elif theme_config == ThemeType.PURPLE_PASSION:
    	table_color = '#5B5C6E'
    elif theme_config == ThemeType.ROMANTIC:
    	table_color = '#F0E8CD'
    elif theme_config == ThemeType.ESSOS:
    	table_color = '#FDFCF5'
    else:
    	table_color = ''
    

    最终实现了多种颜色主题,包含以下。

    6.1 CHALK主题

    6.2 PURPLE主题

    6.3 ESSOS主题

    6.4 ROMANTIC主题

    6.5 DARK主题

    通过5种主题颜色,展示同一个大屏效果,有被炫到嘛?

    七、拖拽演示视频

    拖拽过程演示视频:
    https://www.zhihu.com/zvideo/1502249430140616704

    八、全流程讲解视频

    全流程讲解:
    https://www.zhihu.com/zvideo/1503013679826690048


    by 马哥python说

  • 相关阅读:
    Mybatis对数据加密解密(AES加解密)操作
    01 Python进阶:正则表达式
    Python合并多个相交矩形框
    SAP中外协加工收货与反冲消耗数量不一致的产生原因分析和解决案例二
    激发客户潜在需求
    Linux:systemctl常用命令
    比 eval 和 iframe 更强的新一代 JavaScript 沙箱
    Python15题day13
    github 中的java前后端项目整合到本地运行
    Session,Cookie,Headers,Token,公参都是些啥
  • 原文地址:https://www.cnblogs.com/mashukui/p/16267047.html