Python pyecharts数据可视化实例详解
作者:清&轻
一、数据可视化
1.pyecharts介绍
官方网址:https://pyecharts.org/#/zh-cn/intro
📣 概况:
Echarts 是一个由百度开源的数据可视化,凭借着良好的交互性,精巧的图表设计,使用JavaScript实现的。
而pyechart是由国内的大佬们用python调用Echarts库实现,可以帮助我们轻松搭配出精美的图表。
✨ 特性:
简洁的 API 设计,使用如丝滑般流畅,支持链式调用;
囊括了 30+ 种常见图表,应有尽有;
支持主流 Notebook 环境,Jupyter Notebook 和 JupyterLab;
可轻松集成至 Flask,Django 等主流 Web 框架;
高度灵活的配置项,可轻松搭配出精美的图表;
详细的文档和示例,帮助开发者更快的上手项目;
多达 400+ 地图文件以及原生的百度地图,为地理数据可视化提供强有力的支持。
安装: pip install pyecharts
2.初入了解
(1).快速上手
这是官网上提供的两种写法,链式调用与单独调用写法,全凭自己的习惯。
更多示例:https://gallery.pyecharts.org/#/Bar/stack_bar_percent
from pyecharts.charts import Bar from pyecharts import options as opts # V1 版本开始支持链式调用 # 你所看到的格式其实是 `black` 格式化以后的效果 # 可以执行 `pip install black` 下载使用 bar = ( Bar() .add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]) .add_yaxis("商家A", [5, 20, 36, 10, 75, 90]) .set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题")) # 或者直接使用字典参数 # .set_global_opts(title_opts={"text": "主标题", "subtext": "副标题"}) ) bar.render() # 不习惯链式调用的开发者依旧可以单独调用方法 bar = Bar() bar.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"]) bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90]) bar.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题")) bar.render() # bar.render_notebook()##在jupyter中好用 # render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件 # 也可以传入路径参数,如 bar.render("mycharts.html")
(2).简单的配置项介绍
这里只是提供了感觉能用到的注释介绍,要了解更多的信息还请去官方文档查看,里面的注释、案例也非常地全面。
使用 options 配置项,在 pyecharts 中,一切皆 Options。begin!!!
import pyecharts.options as opts #使用 options 配置项,在 pyecharts 中,一切皆 Options。 from pyecharts.charts import Pie #饼图 from pyecharts.faker import Faker #导入自带的数据 fc = Faker.choose() print('fc', fc) fv = Faker.values() print('fv',fv) ##链式调用写法 c = ( #初始化配置项 Pie( init_opts=opts.InitOpts( # 图表画布宽度,css 长度单位。 width="1200px", # 图表画布高度,css 长度单位。 height="700px", # 网页标题 page_title='我是网页标题', # 图表主题 theme='dark', # 图表背景颜色 bg_color="#2c343c", # 图表 ID,图表唯一标识,用于在多图表时区分。 chart_id='', ) ) .add( "图例", #图例,请用鼠标指向图形区域时查看 [list(z) for z in zip(fc, fv)], ##数据 列表嵌套列表,如:[['衬衫', 97], ['毛衣', 29], ['领带', 109], ['裤子', 117], ['风衣', 53], ['高跟鞋', 85], ['袜子', 143]] # center=["50%", "50%"],#图形居中,默认居中 ) #设置全局配置项 .set_global_opts( # 标题配置项,更多请看官方文档https://pyecharts.org/#/zh-cn/global_options?id=titleopts%ef%bc%9a%e6%a0%87%e9%a2%98%e9%85%8d%e7%bd%ae%e9%a1%b9 title_opts=opts.TitleOpts(title="主标题", title_textstyle_opts=opts.TextStyleOpts(font_size=25),#文本大小 title_link='xxx.html', # 主标题跳转 URL 链接 subtitle='副标题', subtitle_textstyle_opts=opts.TextStyleOpts(font_style='oblique',font_family='Microsoft YaHei', color='#eb1212')#字体风格,字体样式,字体颜色, ), # 图例配置项,更多请看官方文档https://pyecharts.org/#/zh-cn/global_options?id=legendopts%ef%bc%9a%e5%9b%be%e4%be%8b%e9%85%8d%e7%bd%ae%e9%a1%b9 legend_opts=opts.LegendOpts( is_show=True, # 是否显示图例组件 #图例组件离容器左侧的距离。 # left 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比, # 也可以是 'left', 'center', 'right'。 # 如果 left 的值为'left', 'center', 'right',组件会根据相应的位置自动对齐。 pos_left = '900px', # 图例组件离容器右侧的距离。 # right 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。 pos_right = None, # 图例组件离容器上侧的距离。 # top 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比, # 也可以是 'top', 'middle', 'bottom'。 # 如果 top 的值为'top', 'middle', 'bottom',组件会根据相应的位置自动对齐。 pos_top = '30px', # 图例组件离容器下侧的距离。 # bottom 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。 pos_bottom = None, # 图例列表的布局朝向。可选:'horizontal', 'vertical' orient = 'vertical', # 图例标记和文本的对齐。默认自动(auto) # 根据组件的位置和 orient 决定 # 当组件的 left 值为 'right' 以及纵向布局(orient 为 'vertical')的时候为右对齐,即为 'right'。 # 可选参数: `auto`, `left`, `right` align = 'auto', # 图例内边距,单位px,默认各方向内边距为5 padding = 5, # 图例每项之间的间隔。横向布局时为水平间隔,纵向布局时为纵向间隔。 # 默认间隔为 10 item_gap = 10, # 图例标记的图形宽度。默认宽度为 25 item_width = 25, # 图例标记的图形高度。默认高度为 14 item_height = 14, # 图例关闭时的颜色。默认是 #ccc inactive_color = '#ffffff', ), # 视觉映射配置项https://pyecharts.org/#/zh-cn/global_options?id=visualmapopts%ef%bc%9a%e8%a7%86%e8%a7%89%e6%98%a0%e5%b0%84%e9%85%8d%e7%bd%ae%e9%a1%b9 visualmap_opts = opts.VisualMapOpts( # 是否为分段型 is_piecewise = True, # 是否反转 visualMap 组件 is_inverse = False, # 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如: pieces = [ {"min": 1500}, #// 不指定 max,表示 max 为无限大(Infinity)。 # {"min": 900, "max": 1500}, {"min": 310, "max": 1000}, {"min": min(fv), "max": max(fv)},###这里由于数据范围的缘故,导致渲染出的图不好看 {"min": 10, "max": max(fv)/2, "label": f'10 到 {max(fv)/2}(自定义label)'}, {"value": fv[0], "label": '123(自定义特殊颜色)', "color": 'grey'}, #//表示 value 等于 123 的情况 {"value": fv, "label": 'SSS', "color": 'red'}, {"max": 5} #// 不指定 min,表示 min 为无限大(-Infinity)。 ] ), ) #设置系列配置项,https://pyecharts.org/#/zh-cn/series_options?id=itemstyleopts%ef%bc%9a%e5%9b%be%e5%85%83%e6%a0%b7%e5%bc%8f%e9%85%8d%e7%bd%ae%e9%a1%b9 # .set_series_opts(label_opts=opts.LabelOpts(formatter="{b}: {c}")) .render("pie_position.html") )
3.案例实战
本次要对薪资、工作地点、招聘要求里面的经验与学历进行数据处理并可视化。
(1).柱状图Bar
按住鼠标中间滑轮或鼠标左键可进行调控。
import pandas as pd from pyecharts import options as opts python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') python_data['工作地点'] = [i.split('-')[0] for i in python_data['工作地点']] city = python_data['工作地点'].value_counts() ###柱状图 from pyecharts.charts import Bar c = ( Bar() .add_xaxis(city.index.tolist()) #城市列表数据项 .add_yaxis("Python", city.values.tolist())#城市对应的岗位数量列表数据项 .set_global_opts( title_opts=opts.TitleOpts(title="Python招聘岗位所在城市分布情况"), datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")], xaxis_opts=opts.AxisOpts(name='城市'), # 设置x轴名字属性 yaxis_opts=opts.AxisOpts(name='岗位数量'), # 设置y轴名字属性 ) .render("bar_datazoom_both.html") )
(2).地图Map
省份
这里对所在省份进行可视化。
import pandas as pd import copy from pyecharts import options as opts python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') python_data_deepcopy = copy.deepcopy(python_data) #深复制一份数据 python_data['工作地点'] = [i.split('-')[0] for i in python_data['工作地点']] city = python_data['工作地点'].value_counts() city_list = [list(ct) for ct in city.items()] def province_city(): '''这是从接口里爬取的数据(不太准,但是误差也可以忽略不计!)''' area_data = {} with open('./中国省份_城市.txt', mode='r', encoding='utf-8') as f: for line in f: line = line.strip().split('_') area_data[line[0]] = line[1].split(',') province_data = [] for ct in city_list: for k, v in area_data.items(): for i in v: if ct[0] in i: ct[0] = k province_data.append(ct) area_data_deepcopy = copy.deepcopy(area_data) for k in area_data_deepcopy.keys(): area_data_deepcopy[k] = 0 for i in province_data: if i[0] in area_data_deepcopy.keys(): area_data_deepcopy[i[0]] = area_data_deepcopy[i[0]] +i[1] province_data = [[k,v]for k,v in area_data_deepcopy.items()] best = max(area_data_deepcopy.values()) return province_data,best province_data,best = province_city() #地图_中国地图(带省份)Map-VisualMap(连续型) c2 = ( Map() .add( "Python",province_data, "china") .set_global_opts( title_opts=opts.TitleOpts(title="Python招聘岗位——全国分布情况"), visualmap_opts=opts.VisualMapOpts(max_=int(best / 2)), ) .render("map_china.html") )
这是 中国省份_城市.txt 里面的内容,通过[接口]抓取到的中国地区信息。
源码:
import requests import json header = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36", } response = requests.get('https://j.i8tq.com/weather2020/search/city.js',headers=header) result = json.loads(response.text[len('var city_data ='):]) print(result) each_province_data = {} f = open('./中国省份_城市.txt',mode='w',encoding='utf-8') for k,v in result.items(): province = k if k in ['上海', '北京', '天津', '重庆']: city = ','.join(list(v[k].keys())) else: city = ','.join(list(v.keys())) f.write(f'{province}_{city}\n') each_province_data[province] = city f.close() print(each_province_data)
城市
这里对所在城市进行可视化。
import pandas as pd import copy from pyecharts import options as opts python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') python_data_deepcopy = copy.deepcopy(python_data) #深复制一份数据 python_data['工作地点'] = [i.split('-')[0] for i in python_data['工作地点']] city = python_data['工作地点'].value_counts() city_list = [list(ct) for ct in city.items()] ###地图_中国地图(带城市)——Map-VisualMap(分段型) from pyecharts.charts import Map c1 = ( Map(init_opts=opts.InitOpts(width="1244px", height="700px",page_title='Map-中国地图(带城市)', bg_color="#f4f4f4")) .add( "Python", city_list, "china-cities", #地图 label_opts=opts.LabelOpts(is_show=False), ) .set_global_opts( title_opts=opts.TitleOpts(title="Python招聘岗位——全国分布情况"), visualmap_opts=opts.VisualMapOpts(max_=city_list[0][1],is_piecewise=True), ) .render("map_china_cities.html") )
地区
这里对上海地区可视化。
import pandas as pd import copy from pyecharts import options as opts python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') python_data_deepcopy = copy.deepcopy(python_data) #深复制一份数据 shanghai_data = [] sh = shanghai_data.append for i in python_data_deepcopy['工作地点']: if '上海' in i: if len(i.split('-')) > 1: sh(i.split('-')[1]) shanghai_data = pd.Series(shanghai_data).value_counts() shanghai_data_list = [list(sh) for sh in shanghai_data.items()] #上海地图 c3 = ( Map() .add("Python", shanghai_data_list, "上海") ###这个可以更改地区(如:成都)这里改了的话,上面的数据处理也要做相应的更改 .set_global_opts( title_opts=opts.TitleOpts(title="Map-上海地图"), visualmap_opts=opts.VisualMapOpts(max_=shanghai_data_list[0][1]) ) .render("map_shanghai.html") )
(3).饼图Pie
Pie1
from pyecharts import options as opts from pyecharts.charts import Pie import pandas as pd python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') require_list = [] rl = require_list.append for i in python_data['招聘要求']: if '经验' in i: rl(i.split(' ')[1]) else: rl('未知') python_data['招聘要求'] = require_list require = python_data['招聘要求'].value_counts() require_list = [list(ct) for ct in require.items()] print(require_list) c = ( Pie() .add( "", require_list, radius=["40%", "55%"], label_opts=opts.LabelOpts( position="outside", formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}: }{c} {per|{d}%} ", background_color="#eee", border_color="#aaa", border_width=1, border_radius=4, rich={ "a": {"color": "#999", "lineHeight": 22, "align": "center"}, "abg": { "backgroundColor": "#e3e3e3", "width": "100%", "align": "right", "height": 22, "borderRadius": [4, 4, 0, 0], }, "hr": { "borderColor": "#aaa", "width": "100%", "borderWidth": 0.5, "height": 0, }, "b": {"fontSize": 16, "lineHeight": 33}, "per": { "color": "#eee", "backgroundColor": "#334455", "padding": [2, 4], "borderRadius": 2, }, }, ), ) .set_global_opts( title_opts=opts.TitleOpts(title="工作经验要求"), legend_opts=opts.LegendOpts(padding=20, pos_left=500), ) .render("pie_rich_label.html") )
Pie2
from pyecharts import options as opts from pyecharts.charts import Pie import pandas as pd python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') xueli_list = [] xl = xueli_list.append for i in python_data['招聘要求']: if len(i.split(' ')) == 3: xl(i.split(' ')[2]) else: xl('未知') python_data['招聘要求'] = xueli_list xueli_require = python_data['招聘要求'].value_counts() xueli_require_list = [list(ct) for ct in xueli_require.items()] c = ( Pie() .add( "", xueli_require_list, radius=["30%", "55%"], rosetype="area", ) .set_global_opts(title_opts=opts.TitleOpts(title="学历要求")) .render("pie_rosetype.html") )
(4).折线图Line
这里对薪资情况进行可视化。
import pandas as pd import re python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') sal = python_data['薪资'] xin_zi1 = [] xin_zi2 = [] xin_zi3 = [] xin_zi4 = [] xin_zi5 = [] xin_zi6 = [] for s in sal: s = str(s) if '千' in s: xin_zi1.append(s) else: if re.findall('-(.*?)万',s): s = float(re.findall('-(.*?)万',s)[0]) if 1.0<s<=1.5: xin_zi2.append(s) elif 1.5<s<=2.5: xin_zi3.append(s) elif 2.5<s<=3.2: xin_zi4.append(s) elif 3.2<s<=4.0: xin_zi5.append(s) else: xin_zi6.append(s) xin_zi = [['<10k',len(xin_zi1)],['10~15k',len(xin_zi2)],['15<25k',len(xin_zi3)], ['25<32k',len(xin_zi4)],['32<40k',len(xin_zi5)],['>40k',len(xin_zi6),]] import pyecharts.options as opts from pyecharts.charts import Line x, y =[i[0] for i in xin_zi],[i[1] for i in xin_zi] c2 = ( Line() .add_xaxis(x) .add_yaxis( "Python", y, markpoint_opts=opts.MarkPointOpts( data=[opts.MarkPointItem(name="max", coord=[x[2], y[2]], value=y[2])] #name='自定义标记点' ), ) .set_global_opts(title_opts=opts.TitleOpts(title="薪资情况"), xaxis_opts=opts.AxisOpts(name='薪资范围'), # 设置x轴名字属性 yaxis_opts=opts.AxisOpts(name='数量'), # 设置y轴名字属性 ) .render("line_markpoint_custom.html") )
(5).组合图表
最后,将多个html上的图表进行合并成一个html图表。
首先,我们执行下面这串格式的代码(只写了四个图表,自己做相应添加即可)
import pandas as pd from pyecharts.charts import Bar,Map,Pie,Line,Page from pyecharts import options as opts python_data = pd.read_csv('./testDataPython-2022-05-01_11_48_36.csv') python_data['工作地点'] = [i.split('-')[0] for i in python_data['工作地点']] city = python_data['工作地点'].value_counts() city_list = [list(ct) for ct in city.items()] ###柱状图 def bar_datazoom_slider() -> Bar: c = ( Bar() .add_xaxis(city.index.tolist()) #城市列表数据项 .add_yaxis("Python", city.values.tolist())#城市对应的岗位数量列表数据项 .set_global_opts( title_opts=opts.TitleOpts(title="Python招聘岗位所在城市分布情况"), datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")], xaxis_opts=opts.AxisOpts(name='城市'), # 设置x轴名字属性 yaxis_opts=opts.AxisOpts(name='岗位数量'), # 设置y轴名字属性 ) ) return c # 地图_中国地图(带省份)Map-VisualMap(连续型) def map_china() -> Map: import copy area_data = {} with open('./中国省份_城市.txt', mode='r', encoding='utf-8') as f: for line in f: line = line.strip().split('_') area_data[line[0]] = line[1].split(',') province_data = [] for ct in city_list: for k, v in area_data.items(): for i in v: if ct[0] in i: ct[0] = k province_data.append(ct) area_data_deepcopy = copy.deepcopy(area_data) for k in area_data_deepcopy.keys(): area_data_deepcopy[k] = 0 for i in province_data: if i[0] in area_data_deepcopy.keys(): area_data_deepcopy[i[0]] = area_data_deepcopy[i[0]] + i[1] province_data = [[k, v] for k, v in area_data_deepcopy.items()] best = max(area_data_deepcopy.values()) c = ( Map() .add("Python", province_data, "china") .set_global_opts( title_opts=opts.TitleOpts(title="Python招聘岗位——全国分布情况"), visualmap_opts=opts.VisualMapOpts(max_=int(best / 2)), ) ) return c #饼图 def pie_rich_label() -> Pie: require_list = [] rl = require_list.append for i in python_data['招聘要求']: if '经验' in i: rl(i.split(' ')[1]) else: rl('未知') python_data['招聘要求'] = require_list require = python_data['招聘要求'].value_counts() require_list = [list(ct) for ct in require.items()] c = ( Pie() .add( "", require_list, radius=["40%", "55%"], label_opts=opts.LabelOpts( position="outside", formatter="{a|{a}}{abg|}\n{hr|}\n {b|{b}: }{c} {per|{d}%} ", background_color="#eee", border_color="#aaa", border_width=1, border_radius=4, rich={ "a": {"color": "#999", "lineHeight": 22, "align": "center"}, "abg": { "backgroundColor": "#e3e3e3", "width": "100%", "align": "right", "height": 22, "borderRadius": [4, 4, 0, 0], }, "hr": { "borderColor": "#aaa", "width": "100%", "borderWidth": 0.5, "height": 0, }, "b": {"fontSize": 16, "lineHeight": 33}, "per": { "color": "#eee", "backgroundColor": "#334455", "padding": [2, 4], "borderRadius": 2, }, }, ), ) .set_global_opts( title_opts=opts.TitleOpts(title="工作经验要求"), legend_opts=opts.LegendOpts(padding=20, pos_left=500), ) ) return c #折线图 def line_markpoint_custom() -> Line: import re sal = python_data['薪资'] xin_zi1 = [] xin_zi2 = [] xin_zi3 = [] xin_zi4 = [] xin_zi5 = [] xin_zi6 = [] for s in sal: s = str(s) if '千' in s: xin_zi1.append(s) else: if re.findall('-(.*?)万',s): s = float(re.findall('-(.*?)万',s)[0]) if 1.0<s<=1.5: xin_zi2.append(s) elif 1.5<s<=2.5: xin_zi3.append(s) elif 2.5<s<=3.2: xin_zi4.append(s) elif 3.2<s<=4.0: xin_zi5.append(s) else: xin_zi6.append(s) xin_zi = [['<10k',len(xin_zi1)],['10~15k',len(xin_zi2)],['15<25k',len(xin_zi3)], ['25<32k',len(xin_zi4)],['32<40k',len(xin_zi5)],['>40k',len(xin_zi6),]] x, y =[i[0] for i in xin_zi],[i[1] for i in xin_zi] c = ( Line() .add_xaxis(x) .add_yaxis( "Python", y, markpoint_opts=opts.MarkPointOpts( data=[opts.MarkPointItem(name="MAX", coord=[x[2], y[2]], value=y[2])] ), ) .set_global_opts(title_opts=opts.TitleOpts(title="薪资情况"), xaxis_opts=opts.AxisOpts(name='薪资范围'), # 设置x轴名字属性 yaxis_opts=opts.AxisOpts(name='数量'), # 设置y轴名字属性 ) ) return c #合并 def page_draggable_layout(): page = Page(layout=Page.DraggablePageLayout) page.add( bar_datazoom_slider(), map_china(), pie_rich_label(), line_markpoint_custom(), ) page.render("page_draggable_layout.html") if __name__ == "__main__": page_draggable_layout()
执行完后,会在当前目录下生成一个page_draggable_layout.html。
然后我们用浏览器打开,就会看到下面这样,我们可以随便拖动虚线框来进行组合,组合好后点击Save Config就会下载一个chart_config.json,然后在文件中找到它,剪切到py当前目录。
文件放置好后,可以新建一个py文件来执行以下代码,这样就会生成一个resize_render.html,也就完成了。
from pyecharts.charts import Page Page.save_resize_html('./page_draggable_layout.html',cfg_file='chart_config.json')
最后,点击打开resize_render.html,我们合并成功的图表就是这样啦!
对大家有帮助的话,记得点赞收藏一下!!!
二、案例数据获取
这篇博文中有提及:https://www.jb51.net/article/247103.htm
总结
到此这篇关于Python pyecharts数据可视化的文章就介绍到这了,更多相关Python pyecharts数据可视化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!