├── .gitignore
├── 00数据可视化流程和思路
├── example0_1
│ ├── example0_1.py
│ ├── resources
│ │ └── sankey.xlsx
│ └── result
│ │ └── result_ex0_1_sankey.html
└── example0_2
│ ├── example0_2.py
│ ├── resources
│ └── travel_routes.xlsx
│ └── result
│ └── result_ex0_2_geo.html
├── 01比较之柱状图
├── example1_1
│ ├── description.md
│ ├── example1_1.py
│ └── result
│ │ └── fans_likes.html
├── example1_2
│ ├── description.md
│ ├── example1_2.py
│ └── result
│ │ └── company_size.html
├── example1_3
│ ├── description.md
│ ├── example1_3.py
│ └── result
│ │ └── fans_likes_2.html
└── example1_4
│ ├── description.md
│ ├── example1_4.py
│ └── result
│ └── bmi.html
├── 02趋势之折线图
├── example2_1
│ └── example2_1.py
├── example2_2
│ ├── example2_2.py
│ └── result
│ │ └── live_deal.html
├── example2_3
│ ├── example2_3.py
│ └── result
│ │ └── marketing_clicking_area.html
└── example2_4
│ ├── example2_4.py
│ └── result
│ └── weather_tab.html
├── 03柱线叠加图
├── 03-1比较与趋势对照分析
│ └── example3_1
│ │ ├── example3_1.py
│ │ └── result
│ │ └── salary_bar_line.html
└── 03-2主因分析之帕累托图
│ ├── example3_2
│ ├── description.md
│ ├── example3_2.py
│ └── result
│ │ └── math_analysis_pareto.html
│ ├── example3_3
│ ├── description.md
│ ├── example3_3.py
│ └── result
│ │ └── restaurant_pareto.html
│ ├── example3_4
│ ├── description.md
│ ├── example3_4.py
│ └── result
│ │ └── credit_company_pareto.html
│ └── whatisParetoChart.md
├── 04构成和差异之堆叠柱状图
├── 04-1构成和差异结合分析
│ ├── example4_1
│ │ ├── example4_1.py
│ │ └── result
│ │ │ └── sales_stacked_bar.html
│ ├── example4_2
│ │ ├── example4_2.py
│ │ └── result
│ │ │ └── GDP_stacked_bar.html
│ └── example4_3
│ │ └── example4_3.py
└── 04-2变化量分析之瀑布图
│ ├── example4_4
│ ├── example4_4.py
│ └── result
│ │ └── in_out_waterfall_stacked_bar.html
│ └── whatisWaterfallPlot.md
├── 05构成和差异之饼状图
├── 05-1普通饼状图
│ └── example5_1
│ │ └── example5_1.py
├── 05-2环状图、南丁格尔玫瑰图
│ ├── example5_2
│ │ ├── example5_2.py
│ │ └── result
│ │ │ └── web_visit_rose_pie.html
│ ├── example5_3
│ │ ├── example5_3.py
│ │ └── result
│ │ │ └── vip_rose_pie.html
│ └── example5_4
│ │ ├── example5_4.py
│ │ └── result
│ │ └── live_commerce_rose_pie.html
└── whatisPieChart.md
├── 06别把数据直接放程序里之使用openpyxl
├── 06-1openpyxl读取excel数据演示
│ └── example6_1
│ │ ├── example6_1.py
│ │ └── resources
│ │ └── table.xlsx
└── 06-2openpyxl结合可视化演示
│ ├── example6_2
│ ├── example6_2.py
│ ├── resources
│ │ └── table.xlsx
│ └── result
│ │ └── sales_line.html
│ └── example6_3
│ ├── example6_3.py
│ ├── resources
│ └── 核桃销量.xlsx
│ └── result
│ └── nut_sales_line.html
├── 07转化跟踪之漏斗图
├── example7_1
│ ├── example7_1.py
│ └── result
│ │ └── sales_section_funnel.html
├── example7_2
│ ├── example7_2.py
│ └── result
│ │ └── user_conversion_rate_funnel.html
├── example7_3
│ ├── example7_3.py
│ ├── resources
│ │ └── 销售漏斗.xlsx
│ └── result
│ │ ├── teamA_sales_funnel.html
│ │ ├── teamB_sales_funnel.html
│ │ └── teamC_sales_funnel.html
├── example7_4
│ ├── example7_4.py
│ ├── resources
│ │ └── 销售.xlsx
│ └── result
│ │ └── year_funnel_tab.html
└── whatisFunnelChart.md
├── 08多维展示之轮播图
├── example8_1
│ ├── example8_1.py
│ ├── resources
│ │ └── 历年前十大经济体.xlsx
│ └── result
│ │ └── GDP_bar_timeline.html
├── example8_2
│ ├── example8_2.py
│ ├── resources
│ │ └── timeline.xlsx
│ └── result
│ │ └── monthly_sales_timeline.html
├── example8_3
│ ├── example8_3.py
│ ├── resources
│ │ └── 每月销售额.xlsx
│ └── result
│ │ └── sales_rose_pie_timeline.html
└── whatisTimeline.md
├── 09位置之地图
├── example9_1
│ ├── example9_1.py
│ └── result
│ │ └── top10property_world_map.html
├── example9_2
│ ├── example9_2.py
│ ├── resources
│ │ └── 全国降雨量.xlsx
│ └── result
│ │ └── rainfall_china_map.html
└── example9_3
│ ├── example9_3.py
│ ├── resources
│ └── 2010-2017年各省份历年GDP.xlsx
│ └── result
│ └── gdp_map_timeline.html
├── 10局部密度之热力图
├── example10_1
│ ├── example10_1.py
│ ├── resources
│ │ └── 便利店.xlsx
│ └── result
│ │ └── week_order_heatmap.html
└── example10_2
│ ├── example10_2.py
│ ├── resources
│ └── 票价表.xlsx
│ └── result
│ └── ticket_price_heatmap.html
├── 11单页多图之页面组合图
├── example11_1
│ ├── example11_1.py
│ └── result
│ │ └── weiboPhoneCompete_bar_page.html
├── example11_2
│ ├── example11_2.py
│ └── result
│ │ └── sales_rose_funnel_page.html
└── example11_3
│ ├── example11_3.py
│ ├── resources
│ └── hiking1.xlsx
│ └── result
│ └── hikingfan_multigraph_page.html
├── 12数据分布之箱线图
├── example12_1
│ ├── example12_1.py
│ └── result
│ │ └── experiment_gp_boxplot.html
├── example12_2
│ ├── example12_2.py
│ └── result
│ │ └── scores_boxplot.html
└── example12_3
│ ├── example12_3.py
│ └── resources
│ └── titanic.xlsx
├── 13数据流向之桑基图
├── example13_1
│ ├── example13_1.py
│ └── result
│ │ └── purchase_sankey.html
├── example13_2
│ ├── example13_2.py
│ └── result
│ │ └── product_category_sankey.html
├── example13_3
│ ├── example13_3.py
│ └── result
│ │ └── product_sales_sankey.html
├── example13_4
│ ├── example13_4.py
│ └── result
│ │ └── stayup_reason_sankey.html
├── example13_5
│ └── example13_5.py
└── example13_6
│ ├── example13_6.py
│ ├── resources
│ └── song.xlsx
│ └── result
│ └── songList_sankey.html
├── 14相关与分布之散点图
├── example14_1
│ ├── example14_1.py
│ ├── resources
│ │ └── wj.xlsx
│ └── result
│ │ └── attack_income_scatter.html
├── example14_2
│ ├── example14_2.py
│ ├── resources
│ │ └── 日均销量对比.xlsx
│ └── result
│ │ └── product_competitor_scatter.html
└── example14_3
│ ├── example14_3.py
│ ├── resources
│ └── dino1.xlsx
│ └── result
│ └── acplot_scatter.html
├── 15综合评估之雷达图
├── example15_1
│ ├── example15_1.py
│ └── result
│ │ └── air_quality_radar.html
├── example15_2
│ ├── example15_2.py
│ └── result
│ │ └── player_radar.html
└── example15_3
│ ├── example15_3.py
│ ├── resources
│ └── test.xlsx
│ └── result
│ └── phone_display_radar.html
├── 16地理描述之地理坐标图
├── example16_1
│ ├── example16_1.py
│ └── result
│ │ └── travel_geo.html
├── example16_2
│ ├── example16_2.py
│ ├── resources
│ │ └── 全国十年年平均温度.xlsx
│ └── result
│ │ └── TEMP_geo_timeline.html
├── example16_3
│ ├── example16_3.py
│ ├── resources
│ │ └── 全国运输.xlsx
│ └── result
│ │ └── postage_geo.html
├── example16_4
│ ├── example16_4.py
│ └── result
│ │ └── on_business_geo.html
└── example16_5
│ ├── example16_5.py
│ └── resources
│ └── 用户分布.xlsx
├── 17多对多映射联系之关系图
└── example17_1
│ ├── example17_1.py
│ ├── resources
│ └── 知识点.xlsx
│ └── result
│ └── pythonKG_graph.html
├── LICENSE
├── README.md
└── 综合应用:制作可视化大屏
└── 可视化大屏demo
├── result
├── GuangZhou.html
├── config
│ └── page_screen_config.json
└── test
│ └── pagetest.html
└── visual_screen.py
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 | /.idea/modules.xml
131 | /.idea/misc.xml
132 | /.idea/python数据可视化.iml
133 | /.idea/vcs.xml
134 | /.idea/.gitignore
135 | /.idea/inspectionProfiles/profiles_settings.xml
136 | /venv_hbsh/
137 | /.idea/jsLibraryMappings.xml
138 | /.idea/workspace-Michael-Du.xml
139 | /.idea/workspace-Michael-Du-2.xml
140 |
--------------------------------------------------------------------------------
/00数据可视化流程和思路/example0_1/example0_1.py:
--------------------------------------------------------------------------------
1 | # 使用import导入openpyxl模块
2 | import openpyxl
3 | # 使用from...import从pyecharts.charts导入Sankey
4 | from pyecharts.charts import Sankey
5 | # 使用from...import从pyecharts导入options,简写为opts
6 | from pyecharts import options as opts
7 | # 使用from...import从pyecharts.charts导入Page
8 | from pyecharts.charts import Page
9 |
10 | # 使用openpyxl.load_workbook(path)读取文件,赋值给wb
11 | wb = openpyxl.load_workbook("./resources/sankey.xlsx")
12 | # 使用中括号读取工作表对照组和实验组,赋值给sheet_A,sheet_B
13 | sheet_A = wb["对照组"]
14 | sheet_B = wb["实验组"]
15 |
16 |
17 | # 定义函数gen_nodesandlinks传入参数sheet
18 | def gen_nodesandlinks(sheet):
19 | # 定义标签数据列表,赋值给变量list_labels
20 | list_labels = []
21 | # 使用max_row函数,计算sheet的行数
22 | sheet_rows = sheet.max_row
23 | # 通过for循环,读取A列2-sheet_rows行数据
24 | for cell in sheet["A"][2:sheet_rows]:
25 | # .value属性获取单元格值,并用append()函数添加进list_labels
26 | list_labels.append(cell.value)
27 | # 通过for循环,读取B列2-sheet_rows行数据
28 | for cell in sheet["B"][2:sheet_rows]:
29 | # .value属性获取单元格值,并用append()函数添加进list_labels
30 | list_labels.append(cell.value)
31 |
32 | # 使用set()函数对list_labels去重
33 | # 使用list()函数对去重后的结果转化为列表
34 | # 赋值给变量list_nodes
35 | list_nodes = list(set(list_labels))
36 |
37 | # 定义节点列表,赋值给变量nodes
38 | nodes = []
39 | # 通过for循环遍历list_labels
40 | for i in list_nodes:
41 | # 定义字典,赋值给变量dic
42 | dic = {}
43 | # 为dic创建("name":"标签名")键:值对
44 | dic["name"] = i
45 | # 使用append()函数将dic添加进nodes
46 | nodes.append(dic)
47 |
48 | # 定义信息流列表,赋值给变量links
49 | links = []
50 | # 通过for循环,读取sheet的2-sheet_rows行数据
51 | for cell in sheet[2:sheet_rows]:
52 | # 定义字典,赋值给变量dic
53 | dic = {}
54 | # .value属性获取元组索引为0的单元格值,为dic创建("source":"标签名1")键:值对
55 | dic["source"] = cell[0].value
56 | # .value属性获取元组索引为1的单元格值,为dic创建("target":"标签名")键:值对
57 | dic["target"] = cell[1].value
58 | # .value属性获取元组索引为2的单元格值,为dic创建("value":"值")键:值对
59 | dic["value"] = cell[2].value
60 | # 使用append()函数将dic添加进links
61 | links.append(dic)
62 | # 使用return返回(nodes,links)
63 | return (nodes, links)
64 |
65 |
66 | # 定义函数page_Sankey传入参数nodes_links,title_name
67 | def page_Sankey(nodes_links, title_name):
68 | # 使用Sankey()函数创建对象赋值给sankey
69 | # 使用InitOpts(),传入参数theme="dark",bg_color="#253441",赋值给init_opts
70 | sankey = Sankey(init_opts=opts.InitOpts(theme="dark", bg_color="#253441"))
71 |
72 | # 为创建的实例增加名字(sankey)、传入实验组节点和信息流列表
73 | sankey.add("sankey",
74 | nodes=nodes_links[0],
75 | links=nodes_links[1],
76 | # 使用LineStyleOpts(),传入参数opacity=0.3, curve=0.5, color="source",赋值给linestyle_opt
77 | linestyle_opt=opts.LineStyleOpts(opacity=0.3, curve=0.5, color="source"),
78 | # 使用LabelOpts(),传入参数position="right",color="white",font_size=10,赋值给label_opts
79 | label_opts=opts.LabelOpts(position="right", color="white", font_size=10),
80 | # 使用SankeyLevelsOpts(),传入参数depth为0-5、itemstyle_opts,赋值给列表levels
81 | levels=[
82 | opts.SankeyLevelsOpts(depth=0,
83 | # 使用ItemStyleOpts(),传入参数color="#FF8947",border_color="#FF8947"
84 | itemstyle_opts=opts.ItemStyleOpts(color="#FF8947", border_color="#FF8947"))
85 | , opts.SankeyLevelsOpts(depth=1,
86 | # 使用ItemStyleOpts(),传入参数color="#96D15C",border_color="#96D15C"
87 | itemstyle_opts=opts.ItemStyleOpts(color="#96D15C", border_color="#96D15C"))
88 | , opts.SankeyLevelsOpts(depth=2,
89 | # 使用ItemStyleOpts(),传入参数color="#479BED",border_color="#479BED"
90 | itemstyle_opts=opts.ItemStyleOpts(color="#479BED", border_color="#479BED"))
91 | , opts.SankeyLevelsOpts(depth=3,
92 | # 使用ItemStyleOpts(),传入参数color="#55C4CA",border_color="#55C4CA"
93 | itemstyle_opts=opts.ItemStyleOpts(color="#55C4CA", border_color="#55C4CA"))
94 | , opts.SankeyLevelsOpts(depth=4,
95 | # 使用ItemStyleOpts(),传入参数color="#E7BF4F",border_color="#E7BF4F"
96 | itemstyle_opts=opts.ItemStyleOpts(color="#E7BF4F", border_color="#E7BF4F"))
97 | ]
98 | )
99 | # 使用TitleOpts(),传入参数title,赋值给title_opts
100 | # 使用LegendOpts(),传入参数is_show=False,赋值给legend_opts
101 | # 调用set_global_opts()
102 | sankey.set_global_opts(title_opts=opts.TitleOpts(title=title_name), legend_opts=opts.LegendOpts(is_show=False))
103 | # 使用return返回sankey
104 | return sankey
105 |
106 |
107 | # 创建Page对象,并赋值给page
108 | page = Page(layout=Page.DraggablePageLayout)
109 |
110 | # 在add()函数中,分别调用对照组和实验组page_Sankey()函数,图例名分别为"用户路径流转图对照组"和"用户路径流转图实验组"
111 | page.add(page_Sankey(gen_nodesandlinks(sheet_A), "用户路径流转图对照组"), page_Sankey(gen_nodesandlinks(sheet_B), "用户路径流转图实验组"))
112 |
113 | # 使用render()生成桑基图页面组合保存到./result/sankey.html
114 | page.render("./result/result_ex0_1_sankey.html")
115 |
--------------------------------------------------------------------------------
/00数据可视化流程和思路/example0_1/resources/sankey.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/00数据可视化流程和思路/example0_1/resources/sankey.xlsx
--------------------------------------------------------------------------------
/00数据可视化流程和思路/example0_2/example0_2.py:
--------------------------------------------------------------------------------
1 | import openpyxl
2 | from pyecharts.charts import Geo
3 | from pyecharts import options as opts
4 | from pyecharts.commons.utils import JsCode
5 |
6 | wb = openpyxl.load_workbook("./resources/travel_routes.xlsx", data_only=True)
7 | sheet = wb["travel_route"]
8 | routeList = []
9 |
10 | for row in range(2, sheet.max_row + 1):
11 | routeInfo = sheet[row]
12 | data = (routeInfo[0].value, routeInfo[1].value)
13 | routeList.append(data)
14 |
15 | line_color_js = """
16 | new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
17 | offset: 0,
18 | color: '#42AECC'
19 | }, {
20 | offset: 1,
21 | color: '#F5602C'
22 | }], false)
23 | """
24 |
25 | geo = Geo(
26 | init_opts=opts.InitOpts(
27 | theme="dark",
28 | bg_color="#475262")
29 | )
30 |
31 | geo.add_schema(maptype="china",
32 | itemstyle_opts=opts.ItemStyleOpts(
33 | color="#2D3948", border_color="#58667A"),
34 | emphasis_itemstyle_opts=opts.ItemStyleOpts(color="#2a333d"))
35 |
36 | geo.add(
37 | "",
38 | routeList,
39 | type_="lines",
40 | symbol="circle",
41 | symbol_size=10,
42 | effect_opts=opts.EffectOpts(
43 | symbol="circle", symbol_size=4, trail_length=0),
44 | linestyle_opts=opts.LineStyleOpts(
45 | width=2, opacity=0.5, curve=0.1, color=JsCode(line_color_js)),
46 | label_opts=opts.LabelOpts(is_show=False)
47 | )
48 |
49 | geo.render(path="./result/result_ex0_2_geo.html")
50 |
--------------------------------------------------------------------------------
/00数据可视化流程和思路/example0_2/resources/travel_routes.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/00数据可视化流程和思路/example0_2/resources/travel_routes.xlsx
--------------------------------------------------------------------------------
/01比较之柱状图/example1_1/description.md:
--------------------------------------------------------------------------------
1 | # example1_1
2 |
3 | 用途:分析并比较部分网红博主频道的粉丝互动情况。
4 |
5 | > 分析:可视化的目的是``比较``,且考虑到可视化的数据较少,故采用柱状图进行绘制。
6 |
7 | ## Step 1: 准备数据——网红博主的数据表
8 |
9 | **字段名:频道名称 | 粉丝数(单位:万) | 点赞数(单位:万)**
10 |
11 | note:
12 |
13 | 网红博主的数据可能是从网上爬取下来,经过清洗后存放在了excel表格或者csv表格中,最后才读进列表的
14 |
15 | 不过这里,前面的读取和清洗工作就暂时省略了,数据假如就是已经读进来且清洗了,因为我们关键是看数据可视化的思路.
16 |
17 | ***
18 |
19 | ## Step 2: 将上述表格中的数据分列提取出来
20 |
21 | **这一步的作用是准备绘图所需要的数据。**
22 |
23 | 每一个字段对应的值提取出来存储在各自的列表中。
24 |
25 | ## Step 3: 计算点赞收藏量与粉丝量的比值(赞粉比)
26 |
27 | **这一步的作用也是准备绘图需要的数据。**
28 |
29 | **赞粉比**的值在分析中具有较大的参考价值,它可以在一定程度上避免这样的博主:
30 |
31 | 1、低活跃度或低质量的博主
32 |
33 | 2、买僵尸粉的博主
34 |
35 | 3、从其它知名平台刚入驻,老粉多但新平台尚未充分运营的博主
36 |
37 | ***
38 |
39 | ## Step 4: 使用上述数据,绘制柱状图并保存
40 |
41 | **指定x轴数据列表 -> 指定y轴数据列表及其图例 -> 指定保存路径和文件名(.html格式) -> 执行保存**
42 |
43 | 注意:
44 |
45 | x轴和y轴的数据长度应该一致,从而一一对应生成图像
46 |
47 | 添加y轴的同时,一定要指定该数据的图例(series_name),否则运行会不予通过
48 |
49 | ## 附:解决图像显示时x轴部分label(标签)丢失的问题
50 |
51 | 您可以尝试将``example1_1.py``中的下述代码注释掉再运行。
52 |
53 | ```python
54 | # 优化:横坐标文字比较长时候,部分文字被遮挡不进行显示,所以让横坐标文字稍微倾斜45度一点,同时添加一个标题
55 | bar.set_global_opts(
56 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
57 | title_opts=opts.TitleOpts(title="部分博主粉丝与点赞的对比")
58 | )
59 | ```
60 |
61 | 然后你会发现:
62 |
63 | * 嗯?x轴为啥有些标签没有显示出来?不见了!!!
64 |
65 | * 嗯?标题去哪里了?!!
66 |
67 | 在程序中,一开始这句导入``from pyecharts import options as opts``,这里导入的其实就是对图表配置的选项,上述代码通过设置options中的一些内容,实现了向柱状图添加标题,倾斜横坐标label的功能。
68 |
69 | options模块是一个非常实用的模块,后面经常需要它辅助配置图标的一些细节呈现。
--------------------------------------------------------------------------------
/01比较之柱状图/example1_1/example1_1.py:
--------------------------------------------------------------------------------
1 | # 导入os库,方便后续路径的处理
2 | import os
3 | # 导入options 模块并简写为opts
4 | import pyecharts.options as opts
5 | # 从pyecharts.charts中 导入 Bar模块
6 | from pyecharts.charts import Bar
7 |
8 | """Step 0: 预备工作——必要的参数配置
9 |
10 | 提前指定好生成可视化图形的 数据来源路径 和 图形最终的保存路径
11 | """
12 | # resourcesPath这次暂时没有
13 | # 目标存储的路径(相对路径的默认工作区起点为.../examplex_x这个文件夹)
14 | resultPath = "./result"
15 |
16 |
17 | """Step 1: 准备数据——网红博主的数据表
18 |
19 | 字段名:频道名称 | 粉丝数(单位:万) | 点赞数(单位:万)
20 | note:
21 | 网红博主的数据可能是从网上爬取下来,经过清洗后存放在了excel表格或者csv表格中,最后才读进列表的
22 | 不过这里,前面的读取和清洗工作就暂时省略了,数据假如就是已经读进来且清洗了,因为我们关键是看数据可视化的思路
23 | """
24 | channel_infos = [
25 | ("一起画笔记", 12.5, 18.2),
26 | ("我是课代表", 23.1, 15.2),
27 | ("菠萝冰和夏天", 38.5, 222.7),
28 | ("Jeannie花", 15.8, 71.5),
29 | ("Esther天", 14.1, 8.6),
30 | ("爱草莓的小挺", 11.4, 70.5),
31 | ("栀缘", 18.2, 107.7),
32 | ("钢琴上的音乐", 16.5, 128.3),
33 | ("Mu123", 22.6, 109),
34 | ("师008号", 32, 31.7)
35 | ]
36 |
37 |
38 | """Step 2: 将上述表格中的数据分列提取出来
39 | """
40 | # 将10位博主的频道名称存入变量名为'name'的列表中
41 | # name = ["一起画笔记", "我是课代表", "菠萝冰和夏天", "Jeannie花", "Esther天",
42 | # "爱草莓的小挺", "栀缘", "钢琴上的音乐", "Mu123", "师008号"]
43 | name = [channel_info[0] for channel_info in channel_infos]
44 | # 按照博主姓名的顺序,依次将博主的粉丝数量存入变量名为'fans'的列表中
45 | # fans = [12.5, 23.1, 38.5, 15.8, 14.1, 11.4, 18.2, 16.5, 22.6, 32]
46 | fans = [channel_info[1] for channel_info in channel_infos]
47 | # 按照博主姓名的顺序,依次将博主的点赞收藏量存入变量名为‘likes’的列表中
48 | # likes = [18.2, 15.2, 222.7, 71.5, 8.6, 70.5, 107.7, 128.3, 109, 31.7]
49 | likes = [channel_info[2] for channel_info in channel_infos]
50 |
51 |
52 | """Step 3: 计算点赞收藏量与粉丝量的比值(赞粉比)
53 |
54 | 赞粉比数值具有较大的参考价值,它可以在一定程度上避免这样的博主:
55 | 1、低活跃度或低质量博主
56 | 2、买僵尸粉博主
57 | 3、从其它知名平台刚入驻,老粉多但新平台尚未充分运营的博主
58 | """
59 | # 定义一个空列表ratioList,存储点赞收藏量与粉丝量的比值
60 | ratioList = []
61 | # 统计点赞收藏量列表长度,并赋值给length
62 | length = len(channel_infos)
63 | # 将点赞收藏量列表中的值除以对应粉丝量列表中的值,并使用round()函数取近似值并保留2位小数,存储到ratioList列表中
64 | for i in range(length):
65 | ratio = round(likes[i] / fans[i], 2)
66 | ratioList.append(ratio)
67 |
68 |
69 | """Step 4: 使用上述数据,绘制柱状图并保存
70 |
71 | 指定x轴数据列表 -> 指定y轴数据列表及其图例 -> 指定保存路径和文件名(.html格式)执行保存
72 | 注意:
73 | x轴和y轴的数据长度应该一致,从而一一对应生成图像
74 | 添加y轴的同时,一定要指定该数据的图例(series_name),否则运行会不予通过
75 | """
76 | # 创建一个柱状图Bar对象并赋值给变量bar
77 | bar = Bar()
78 | # 给柱状图添加x轴数据,数据内容是博主姓名列表:name
79 | bar.add_xaxis(xaxis_data=name)
80 | # 给柱状图添加y轴数据,数据内容是赞粉比列表:ratioList,指定该数据的图例为”赞粉比“
81 | bar.add_yaxis(y_axis=ratioList, series_name="赞粉比")
82 | # 优化:横坐标文字比较长时候,部分文字被遮挡不进行显示,所以让横坐标文字稍微倾斜45度一点,同时添加一个标题
83 | bar.set_global_opts(
84 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
85 | title_opts=opts.TitleOpts(title="部分博主粉丝与点赞的对比")
86 | )
87 | # 绘制出这条柱状图,并保存到路径"./result/fans_likes.html"
88 | resultFileName = "fans_likes.html"
89 | bar.render(path=os.path.join(resultPath, resultFileName))
90 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_2/description.md:
--------------------------------------------------------------------------------
1 | # example1_2
2 |
3 | 用途:分析并比较一些公司的员工人数情况。
4 |
5 | > 分析:可视化的目的是``比较``,且考虑到可视化的数据较少,故采用柱状图进行绘制。
6 |
7 | ## Step 1: 准备所需的绘图数据——公司及员工人数信息表
8 |
9 | **字段名:公司名 | 公司员工人数**
10 |
11 | 这里略去从表格中提取数据的情形,直接假设已经把相应字段读进了所需的列表中
12 |
13 | 且所获得的数据已经是我们所要的坐标轴数据,不需要再做计算处理了,直接对应放上坐标系即可
14 |
15 | > 其实这一步相当于已经把example1_1的前3步合并到一起了哈哈哈。不过不管怎么变,它的意图都是读取数据、预备坐标轴上的数据,这点总是不变的。
16 |
17 | ***
18 |
19 | ## Step 2: 使用上述数据,绘制柱状图并保存
20 |
21 | **创建柱状图并指定图表标题 -> 指定x轴数据列表 -> 指定y轴数据列表及其图例 -> 指定保存路径和文件名(.html格式) -> 执行保存**
22 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_2/example1_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | # 使用from...import从pyecharts.charts中导入Bar模块
3 | from pyecharts.charts import Bar
4 | # 使用from...import从pyecharts中导入options模块并简写为opts
5 | from pyecharts import options as opts
6 |
7 | # 目标存储的路径
8 | resultPath = "./result"
9 |
10 | """数据来源(简化到已经清洗完毕并读取至列表的情形)"""
11 | # 将公司的名字存入变量名为"name"的列表中
12 | name = ["ibm", "microsoft", "pwc", "citi", "amazon", "apple", "ey", "walmart", "siemens", "google"]
13 | # 按照公司名字的顺序,依次将公司的人数存入变量名为"employee"的列表中
14 | employee = [274047, 116196, 111372, 101482, 93247, 90095, 158363, 120753, 87381, 75109]
15 |
16 | """绘图"""
17 | # 创建Bar对象,并赋值给bar
18 | bar = Bar()
19 | # 设置图表的标题为“公司人数对比”
20 | bar.set_global_opts(title_opts=opts.TitleOpts(title="公司人数对比"))
21 | # 传入参数xaxis_data=name使用add_xaxis()设置x轴为公司名称
22 | bar.add_xaxis(xaxis_data=name)
23 | # 传入参数y_axis=employee,使用add_yaxis()设置y轴图例为“公司人数”
24 | bar.add_yaxis(y_axis=employee, series_name="公司人数")
25 | # 使用render()绘制柱状图保存
26 | resultFileName = "company_size.html"
27 | bar.render(path=os.path.join(resultPath, resultFileName))
28 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_2/result/company_size.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_3/description.md:
--------------------------------------------------------------------------------
1 | # example1_3
2 |
3 | 该示例是``example1_1``的变式。这个问题中我们不再用赞粉比作为y轴数据,而是**直接拿粉丝数和点赞数同时作为y轴直观呈现**。
4 |
5 | 用途:分析并比较部分网红博主频道的粉丝互动情况。
6 |
7 | > 分析:可视化的目的是``比较``,且考虑到可视化的数据较少,故采用柱状图进行绘制,且这个柱状图是``多y轴``的柱状图
8 |
9 | ## Step 1: 准备数据——网红博主的数据表
10 |
11 | 省略,与``example1_1``完全相同。
12 |
13 | ***
14 |
15 | ## Step 2: 将上述表格中的数据分列提取出来
16 |
17 | 省略,与``example1_1``完全相同。
18 |
19 | ***
20 |
21 | ## Step 3: 使用上述数据,绘制柱状图并保存
22 |
23 | **指定x轴数据列表 -> 指定y轴数据列表及其图例 -> 指定保存路径和文件名(.html格式) -> 执行保存**
24 |
25 | > 注意,这一次y轴有两个量,一个是粉丝数,一个是点赞量,分别添加
26 |
27 | 其中上述步骤中还要设置图表配置项,添加标题并且避免横坐标显示不完全(旋转一下横坐标label)
28 |
29 | ## 附1:做图——想一次到位还是分步组装?
30 |
31 | 本例子在绘图的时候有一段很长的构造和设置多y轴柱状图的代码。
32 |
33 | ```python
34 | bar = (Bar()
35 | .set_global_opts(title_opts=opts.TitleOpts(title="博主粉丝数和点赞数"),
36 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)))
37 | .add_xaxis(xaxis_data=name)
38 | .add_yaxis(y_axis=fans, series_name="粉丝数")
39 | .add_yaxis(y_axis=likes, series_name="点赞数")
40 | )
41 | ```
42 |
43 | 其实这跟一步一步创建柱状图呈现的效果是一样的,即**上述代码与下述效果等同**。
44 |
45 | ```python
46 | bar = Bar()
47 | bar.set_global_opts(title_opts=opts.TitleOpts(title="博主粉丝数和点赞数"),
48 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)))
49 | bar.add_xaxis(xaxis_data=name)
50 | bar.add_yaxis(y_axis=fans, series_name="粉丝数")
51 | bar.add_yaxis(y_axis=likes, series_name="点赞数")
52 | ```
53 |
54 | > 第一种写法是``pyecharts``官方文档给出demo(传送门:https://gallery.pyecharts.org/ )中惯用的代码写,其实就是把很多步设置一步到位了。
55 | > 我个人觉得第一种写法更好,一句话创建一个图表,显得更聚集一些,省得创建个图表都要写好几行。
56 | > 不过真正地到底哪种写法更好,仁者见仁智者见智的事情而已。
57 |
58 | ## 附2:全局选项设置——必须一步到位的地方!
59 |
60 | 本问题对柱状图进行调整的时候,做了**添加标题**和**倾斜横坐标文字**两件事,用到了**配置图表的全局选项设置**,即
61 |
62 | ```python
63 | bar.set_global_opts(title_opts=opts.TitleOpts(title="博主粉丝数和点赞数"),
64 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)
65 | )
66 | ```
67 |
68 | > 不同于``附1``可以一步到位或者一步步慢慢来,这里若要同时让两个设置同时起效,必须在一个``set_global_opt``函数里同时配置相应参数,必须一步到位。
69 |
70 | 如果按照下述方式配置柱状图属性:
71 |
72 | ```python
73 | bar.set_global_opts(title_opts=opts.TitleOpts(title="博主粉丝数和点赞数"))
74 | bar.set_global_opts(xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45))
75 | ```
76 |
77 | 可以试试,发现**原来标题的设置消失了,被横坐标label旋转的设置覆盖了**。
78 |
79 | ## 附3:图表属性选项(options)配置中的等效写法
80 |
81 | 以横坐标旋转45度为例,下面两种设置写法**效果等价**,均能正常绘图。
82 |
83 | * 写法1
84 |
85 | ```python
86 | bar.set_global_opts(xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45))
87 | ```
88 |
89 | * 写法2
90 |
91 | ```python
92 | bar.set_global_opts(xaxis_opts=opts.AxisOpts(axislabel_opts={"rotate":45}))
93 | ```
94 |
95 | > 喜欢哪种?还是一样这里仁者见仁智者见智。
96 | > 目前我个人比较习惯写法1,虽然写起来稍微绕一点,但不管怎么说Pycharm中有代码提示引导,也还是挺香的。
97 | >
98 | > ``pyecharts``官方对此也有相应说明,传送门:https://pyecharts.org/#/zh-cn/parameters
99 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_3/example1_3.py:
--------------------------------------------------------------------------------
1 | # 导入os库,方便后续路径的处理
2 | import os
3 | # 导入options 模块并简写为opts
4 | import pyecharts.options as opts
5 | # 从pyecharts.charts中 导入 Bar模块
6 | from pyecharts.charts import Bar
7 |
8 | """Step 0: 预备工作——必要的参数配置
9 | """
10 | # 目标存储的路径
11 | resultPath = "./result"
12 |
13 |
14 | """Step 1: 准备数据——网红博主的数据表
15 | 字段名:频道名称 | 粉丝数(单位:万) | 点赞数(单位:万)
16 | """
17 | channel_infos = [
18 | ("一起画笔记", 12.5, 18.2),
19 | ("我是课代表", 23.1, 15.2),
20 | ("菠萝冰和夏天", 38.5, 222.7),
21 | ("Jeannie花", 15.8, 71.5),
22 | ("Esther天", 14.1, 8.6),
23 | ("爱草莓的小挺", 11.4, 70.5),
24 | ("栀缘", 18.2, 107.7),
25 | ("钢琴上的音乐", 16.5, 128.3),
26 | ("Mu123", 22.6, 109),
27 | ("师008号", 32, 31.7)
28 | ]
29 |
30 |
31 | """Step 2: 将上述表格中的数据分列提取出来
32 | """
33 | # 将10位博主的频道名称存入变量名为'name'的列表中
34 | # name = ["一起画笔记", "我是课代表", "菠萝冰和夏天", "Jeannie花", "Esther天",
35 | # "爱草莓的小挺", "栀缘", "钢琴上的音乐", "Mu123", "师008号"]
36 | name = [channel_info[0] for channel_info in channel_infos]
37 | # 按照博主姓名的顺序,依次将博主的粉丝数量存入变量名为'fans'的列表中
38 | # fans = [12.5, 23.1, 38.5, 15.8, 14.1, 11.4, 18.2, 16.5, 22.6, 32]
39 | fans = [channel_info[1] for channel_info in channel_infos]
40 | # 按照博主姓名的顺序,依次将博主的点赞收藏量存入变量名为‘likes’的列表中
41 | # likes = [18.2, 15.2, 222.7, 71.5, 8.6, 70.5, 107.7, 128.3, 109, 31.7]
42 | likes = [channel_info[2] for channel_info in channel_infos]
43 |
44 |
45 | """Step 3: 使用上述数据,绘制柱状图并保存
46 |
47 | 注意:
48 | 1、这一次记得设置全局配置,设置标题并调整x轴显示不完全的问题
49 | 2、这次绘制的是多y轴柱状图(y轴有点赞量和粉丝数2项合到一张图)
50 | 3、本案例中采用pyecharts官方文档中常用的一句话到底的写法
51 | """
52 | # # 创建一个柱状图Bar对象并赋值给变量bar
53 | # bar = Bar()
54 | # # 给柱状图添加x轴数据,数据内容是博主姓名列表:name
55 | # bar.add_xaxis(xaxis_data=name)
56 | # # 给柱状图添加y轴数据,y轴数据有粉丝数和点赞量两个
57 | # bar.add_yaxis(y_axis=fans, series_name="粉丝数")
58 | # bar.add_yaxis(y_axis=likes, series_name="点赞数")
59 | # # 优化:横坐标文字比较长时候,部分文字被遮挡不进行显示,所以让横坐标文字稍微倾斜45度一点,同时添加一个标题
60 | # bar.set_global_opts(
61 | # xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
62 | # title_opts=opts.TitleOpts(title="博主粉丝数和点赞数")
63 | # )
64 | """下述代码与上述注释代码等价"""
65 | bar = (Bar()
66 | .set_global_opts(title_opts=opts.TitleOpts(title="博主粉丝数和点赞数"),
67 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)))
68 | .add_xaxis(xaxis_data=name)
69 | .add_yaxis(y_axis=fans, series_name="粉丝数")
70 | .add_yaxis(y_axis=likes, series_name="点赞数")
71 | )
72 |
73 | # 绘制出这条柱状图,并保存到路径"./result/fans_likes.html"
74 | resultFileName = "fans_likes_2.html"
75 | bar.render(path=os.path.join(resultPath, resultFileName))
76 |
--------------------------------------------------------------------------------
/01比较之柱状图/example1_4/description.md:
--------------------------------------------------------------------------------
1 | # example1_4
2 |
3 | 用途:比较统计5名学生的BMI指数。公式:``bmi = weight/(height*height)``
4 |
5 | > 分析:可视化的目的是``比较``,且考虑到可视化的数据较少,故采用柱状图进行绘制。
6 |
7 | 看完前3个example了以后,这个不是简单的一批吗?
8 |
9 | ## Step 1: 读表,取各列数据
10 |
11 | 学生姓名可作为柱状图x轴,在这一步取出。
12 |
13 | ## Step 2: 利用身高、体重数据算出BMI指数
14 |
15 | 作为y轴的BMI数据在这一步得出
16 |
17 | ## Step 3: 制图
18 |
19 | > Note: 制图时对图像的设置,最好是留下注释,不然时间久了全忘了。
20 |
21 | 以本例为例,简要交代一些图表设置信息即可。
22 |
23 | ```python
24 | """作图
25 |
26 | 标题:BMI数据统计
27 | x轴:学生姓名
28 | y轴:bmi值计算结果,图例无
29 | 存储位置:./result/bmi.html
30 | """
31 | resultFileName = "bmi.html"
32 | bar = (Bar().set_global_opts(title_opts=opts.TitleOpts(title="BMI数据统计"))
33 | .add_xaxis(xaxis_data=name)
34 | .add_yaxis(y_axis=bmiList, series_name="")
35 | .render(path=os.path.join(resultPath, resultFileName))
36 | )
37 | ```
--------------------------------------------------------------------------------
/01比较之柱状图/example1_4/example1_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pyecharts.options as opts
3 | from pyecharts.charts import Bar
4 |
5 | """指定存储目录
6 | """
7 | resultPath = "./result"
8 |
9 | """原始数据表(省略获取、清晰、从文件读取等逻辑)
10 |
11 | 字段:姓名 | 身高(单位:米) | 体重(单位:千克)
12 | """
13 | student_infos = [
14 | ('yoyo', 1.55, 45),
15 | ('coco', 1.6, 50),
16 | ('jojo', 1.58, 48),
17 | ('momo', 1.68, 55),
18 | ('bobo', 1.65, 49)
19 | ]
20 |
21 | """提取表格各列数据,准备包括后续充当x轴的name等字段
22 | """
23 | # 将5位同学的姓名存入变量名为'name'的列表中
24 | name = [student_info[0] for student_info in student_infos]
25 | # 按照同学姓名的顺序,依次将同学的身高存入变量名为'height'的列表中
26 | height = [student_info[1] for student_info in student_infos]
27 | # 按照同学姓名的顺序,依次将同学的体重存入变量名为‘weight’的列表中
28 | weight = [student_info[2] for student_info in student_infos]
29 |
30 | """计算BMI,准备x轴字段对应y轴数据
31 | """
32 | bmiList = []
33 | for one_name, one_height, one_weight in student_infos:
34 | # 保留整数
35 | bmiList.append(
36 | # round(one_weight/(one_height**2), 0)
37 | round(one_weight / (one_height ** 2))
38 | )
39 |
40 | """作图
41 |
42 | 标题:BMI数据统计
43 | x轴:学生姓名
44 | y轴:bmi值计算结果,图例无
45 | 存储位置:./result/bmi.html
46 | """
47 | resultFileName = "bmi.html"
48 | bar = (Bar().set_global_opts(title_opts=opts.TitleOpts(title="BMI数据统计"))
49 | .add_xaxis(xaxis_data=name)
50 | .add_yaxis(y_axis=bmiList, series_name="")
51 | .render(path=os.path.join(resultPath, resultFileName))
52 | )
--------------------------------------------------------------------------------
/01比较之柱状图/example1_4/result/bmi.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/02趋势之折线图/example2_1/example2_1.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/02趋势之折线图/example2_1/example2_1.py
--------------------------------------------------------------------------------
/02趋势之折线图/example2_2/example2_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Line
3 | import pyecharts.options as opts
4 |
5 | """读取数据(读表过程略去,这里聚焦加载文件数据过后的情景)
6 |
7 | 原始数据是这样的二维表,或者每个姓名作为一个单独的Worksheet(工作表)
8 |
9 | | 1月 | 2月 | 3月 | ... | 11月 | 12月
10 | huanhuan|
11 | shushu | (中间放主播的带货成交额数据)
12 | binbin |
13 | """
14 | # 三位主播的带货成交额数据存入下列列表中
15 | huanhuan = [2.3, 2.3, 1.3, 1.2, 2.4, 3.6, 3.5, 3.4, 2.2, 5.5, 10.1, 9.2]
16 | shushu = [5.2, 4.9, 4.6, 4.7, 4.4, 5.6, 5.5, 5.5, 4.1, 6.5, 5.0, 5.2]
17 | binbin = [3.2, 3.3, 5.6, 5.4, 3.6, 4.2, 4.5, 2.5, 8.1, 8.6, 8.8, 6.3]
18 | # 将12各月份并赋值给变量month
19 | month = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
20 |
21 | """制图(属性可以查阅pyecharts官方文档)
22 |
23 | 1、横坐标为月份,纵坐标是各主播带货的月成交额情况
24 | 2、曲线是平滑的
25 | 3、多曲线(添加多个y轴)
26 | 4、曲线上点的形状(标记)设置:
27 | huanhuan的折线,标记(symbol)设为"circle"。
28 | shushu的折线,标记设为"rect"。
29 | binbin的折线,标记设为"triangle"。
30 | (symbol取值是什么是从官方文档找出来的,并不是自己瞎写的)
31 | 5、标记的大小均为10
32 | 6、保存
33 | """
34 | line = (Line()
35 | .add_xaxis(xaxis_data=month)
36 | .add_yaxis(series_name="huanhuan", y_axis=huanhuan,
37 | symbol="circle", symbol_size=10,
38 | is_smooth=True)
39 | .add_yaxis(series_name="shushu", y_axis=shushu,
40 | symbol="rect", symbol_size=10,
41 | is_smooth=True)
42 | .add_yaxis(series_name="binbin", y_axis=binbin,
43 | symbol="triangle", symbol_size=10,
44 | is_smooth=True)
45 | )
46 | # 存储目录
47 | resultPath = "./result"
48 | # 文件名
49 | resultFileName = "live_deal.html"
50 | # 执行保存
51 | line.render(path=os.path.join(resultPath, resultFileName))
52 |
--------------------------------------------------------------------------------
/02趋势之折线图/example2_3/example2_3.py:
--------------------------------------------------------------------------------
1 | import pyecharts.options as opts
2 | from pyecharts.charts import Line
3 | import os
4 |
5 | """准备数据"""
6 | # 将周一至周日并赋值给变量data
7 | data = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
8 | # 将不同营销渠道的点击量数据存入下列列表中
9 | # 邮件营销点击量
10 | email = [120, 132, 101, 134, 90, 230, 210]
11 | # 视频推广点击量
12 | video = [150, 232, 201, 154, 190, 330, 410]
13 |
14 | """执行绘图
15 |
16 | 1、折线图的标题为“营销渠道点击对比”
17 | 2、x轴是data
18 | 3、y轴数据有两项:一个是email,图例设为“邮件营销”;另一个是video,图例设为“视频推广”
19 | 4、y轴设定后的曲线都是光滑的
20 | 5、y轴下方要有阴影,设置透明度为50%(areastyle_opts,这个用法可以查看pyecharts官方文档)
21 | """
22 | line = (Line()
23 | .set_global_opts(title_opts=opts.TitleOpts(title="营销渠道点击对比"))
24 | .add_xaxis(xaxis_data=data)
25 | .add_yaxis(series_name="邮件营销", y_axis=email,
26 | is_smooth=True,
27 | areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
28 | .add_yaxis(series_name="视频推广", y_axis=video,
29 | is_smooth=True,
30 | areastyle_opts=opts.AreaStyleOpts(opacity=0.5))
31 | )
32 |
33 | # 保存路径
34 | resultPath = "./result"
35 | if not os.path.exists(resultPath):
36 | os.mkdir(path=resultPath)
37 | # 保存文件名
38 | resultFileName = "marketing_clicking_area.html"
39 | # 执行保存
40 | line.render(path=os.path.join(resultPath, resultFileName))
41 |
--------------------------------------------------------------------------------
/02趋势之折线图/example2_4/example2_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Line, Tab
3 | import pyecharts.options as opts
4 |
5 | """数据来源(可能来自一个多sheet的excel表格,这里简化读表过程)"""
6 | # 具体的气候数据存入下列列表中
7 | # 最高平局气温数据
8 | weather_dict = {
9 | # 平均最高气温
10 | "Average_highest": [8.1, 8.4, 11.3, 14.2, 17.9, 21.2, 23.5, 23.2, 20.2, 15.5, 11.1, 8.3],
11 | # 日均气温数据
12 | "Daily_mean": [5.2, 5.3, 7.6, 9.9, 13.3, 16.5, 18.7, 18.5, 15.7, 12.0, 8.0, 5.5],
13 | # 平均最低气温
14 | "Average_lowest": [2.3, 2.1, 3.9, 5.5, 8.7, 11.7, 13.9, 13.7, 11.4, 8.4, 4.9, 2.7],
15 | # 平均降水量
16 | "Average_precipitation": [55.2, 40.9, 41.6, 43.7, 49.4, 45.1, 44.5, 49.5, 49.1, 68.5, 59.0, 55.2],
17 | # 平均紫外线强度
18 | "Average_ultraviolet_index": [1, 1, 2, 4, 5, 6, 6, 5, 4, 2, 1, 0],
19 | # 平均日照时间
20 | "Mean_monthly_sunshine_hours": [61.5, 77.9, 114.6, 168.7, 198.5, 204.3, 212.0, 204.7, 149.3, 116.5, 72.6, 52.0]
21 | }
22 | # 气候数据的指标名称存入列表weather_key_list中(每个Tab维度的名称)
23 | weather_key_list = list(weather_dict.keys())
24 | # 将气候数据存入列表weather_value_list中(每个Tab维度下的y轴数据)
25 | weather_value_list = list(weather_dict.values())
26 | # 将12各月份并赋值给变量month(x轴信息)
27 | month = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
28 |
29 |
30 | def create_line(x_axis_data, y_axis_data, legend_name) -> Line:
31 | """绘制曲线
32 |
33 | 1、x轴是月份
34 | 2、y轴是不同的气候数据系列的取值
35 | 3、y轴图例是数据系列名,其中的下划线要全部换成空格
36 | 4、每个系列的y轴取值的最大值和最小值要格外强调标注出来
37 | (markpoint_opts,这个标定有点套娃,我是看pyecharts官方文档干出来的)
38 | 5、符合上述方法的图形要批量创建,用函数封装
39 |
40 | @:param x_axis_data x轴信息
41 | @:param y_axis_data y轴数据
42 | @:param legend_name y轴数据对应的图例
43 |
44 | @:return 创建好的曲线图Line对象
45 | """
46 | line = (Line()
47 | .add_xaxis(xaxis_data=x_axis_data)
48 | .add_yaxis(series_name=legend_name, y_axis=y_axis_data,
49 | markpoint_opts=opts.MarkPointOpts(data=[opts.MarkPointItem(type_="max"),
50 | opts.MarkPointItem(type_="min")])
51 | )
52 | )
53 | return line
54 |
55 |
56 | """建立看板,可切换不同的折线图进行观察,因为后面要添加多张折线图
57 | """
58 | tab = Tab()
59 | # 逐个创建新的曲线并添加至tab看板下
60 | for weather_key, weather_value in weather_dict.items():
61 | # 把weather_key中的下划线换成空格呈现在最终的折线图中
62 | weather_key_modified = weather_key.replace("_", " ")
63 | tab.add(
64 | chart=create_line(x_axis_data=month, y_axis_data=weather_value, legend_name=weather_key_modified),
65 | tab_name=weather_key_modified
66 | )
67 |
68 | # 保存路径
69 | resultPath = "./result"
70 | if not os.path.exists(path=resultPath):
71 | os.mkdir(path=resultPath)
72 | # 保存文件名
73 | resultFileName = "weather_tab.html"
74 | # 执行多折线图看板的保存
75 | tab.render(path=os.path.join(resultPath, resultFileName))
76 |
--------------------------------------------------------------------------------
/03柱线叠加图/03-1比较与趋势对照分析/example3_1/example3_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Line, Bar
3 | import pyecharts.options as opts
4 |
5 | """原始数据:日本男女收入情况调查
6 |
7 | 很巧,这次原始数据就是柱状图所需的x轴和y轴数据。
8 |
9 | 字段:年龄段 | 男性收入 | 女性收入
10 | """
11 | # 定义存储年龄区间,男性收入、女性收入和平均收入数据列表
12 | # x轴(公共)
13 | ageList = ['<20', '20-24', '25-29', '30-34', '35-39', '40-44', '45-49', '50-54', '55-59', '60-64', '65-69', '>=70']
14 | # y轴(两组数据)
15 | male_salaryList = [145, 262, 367, 434, 498, 570, 623, 641, 616, 457, 379, 374]
16 | female_salaryList = [106, 231, 295, 296, 292, 284, 286, 276, 261, 214, 205, 215]
17 |
18 | # 准备折线图的数据(男女平均值)
19 | average_salaryList = [(male_salary + female_salary) / 2
20 | for male_index, male_salary in enumerate(male_salaryList)
21 | for female_index, female_salary in enumerate(female_salaryList)
22 | if male_index == female_index]
23 | # 二元变量条件筛选有没有用笛卡尔积组合?可以输出验证一下。使用if做下标限制就不会出现笛卡尔积提取数据问题了
24 | # print(average_salaryList)
25 |
26 |
27 | """绘制柱线叠加图
28 |
29 | 1. 将年龄段作为x轴;
30 | 2. 将日本男性和女性收入数据作为y轴绘制柱状图;图例分别为“男性收入”“女性收入”
31 | 3. 将男女收入的平均值,作为y轴绘制折线图;y轴这里可以共享同一个坐标系
32 | 4. 将折线图叠加在柱状图上;叠加后注意折线图在更高图层,防止被柱子遮挡!!!
33 | 5. 将整个图表的标题设置为:日本男女收入情况调查;
34 | 6. 将图表保存
35 | """
36 | # 保存路径
37 | resultPath = "./result"
38 | if not os.path.exists(path=resultPath):
39 | os.mkdir(path=resultPath)
40 | # 保存文件名
41 | resultFileName = "salary_bar_line.html"
42 |
43 | bar_line = (
44 | Bar()
45 | .set_global_opts(title_opts=opts.TitleOpts(title="日本男女收入情况调查"))
46 | .add_xaxis(xaxis_data=ageList)
47 | .add_yaxis(series_name="男性收入", y_axis=male_salaryList)
48 | .add_yaxis(series_name="女性收入", y_axis=female_salaryList)
49 | .overlap(chart=(
50 | Line()
51 | .add_xaxis(xaxis_data=ageList)
52 | .add_yaxis(series_name="平均收入", y_axis=average_salaryList, z_level=1) # 提升图层
53 | ))
54 | .render(path=os.path.join(resultPath, resultFileName))
55 | )
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_2/description.md:
--------------------------------------------------------------------------------
1 | # example3_2
2 |
3 | ## 1 案例背景
4 |
5 | 高三备考期间,某个年级最近一次数学考试整体考得稀烂。
6 |
7 | 备课组组长老师快要气秃了,于是决定:
8 |
9 | * 调查一下各种题型的扣分情况
10 |
11 | * 决定下周就哪些扣分严重的项目展开专题习题课
12 |
13 | > One fact: 如果所有题型都能在下周开专题习题课那当然是最好,
14 | > 但是老师们精力有限,还要考虑到学生的消化能力。
15 |
16 | 因此**不能在下周一次性覆盖到所有题型的专题**,所以要想**哪些扣分知识点最主要**应当**优先**上专题课,
17 | 从而在接下来一周**时间、精力有限的条件下**,尽**最大程度**地解决问题。
18 |
19 | ## 2 图像选择:帕累托图(Pareto Chart)
20 |
21 | ### 2.1 什么是帕累托图
22 |
23 | 帕累托图的本质是一个柱状图和一个折线图的叠加,二者共x轴,分别使用不同的y轴。
24 |
25 | * 柱状图部分的y轴:x轴字段对应的直接数据。且帕累托图绘制时要求从左到右**y轴必须自大到小排列下来**
26 | (当然y轴讲顺序x轴也会对应上的......)
27 |
28 | * 折线图部分的y轴:x轴当前字段,**加上当前字段之前所有字段**,的柱状图的**面积占比**,
29 | 所以由此可以发现,折线图在帕累托图中**始终是向上趋势,且上升到最后一个x轴字段的时候值一定是100%**
30 |
31 | ### 2.2 帕累托图的意义和作用
32 |
33 | 意义:
34 |
35 | * 柱状图的意义:y轴从大到小排开,能够表现出x轴字段的**优先情况(重要性)**
36 |
37 | * 折线图的意义:反映出x轴字段代表的事件在依照优先次序处理的情况下**完成的进度**
38 |
39 | 作用:
40 |
41 | 结合**80-20原则**,折线图80%处经过的x轴字段,重要性往往较高(柱状图直接取值很大),
42 | 在条件有限的情况下,先处理掉前80%的内容,可以在**控制成本的条件下尽快抓住问题主要矛盾着手应对**,提升效率。
43 |
44 | > 以本例为说明:备课组老师利用帕累托图可以这样决策备课
45 |
46 | * 柱状图:把知识点按扣分情况排序
47 |
48 | * 折线图:找到80%取值的位置,选出之前所有的知识点
49 |
50 | * 决策:先组织年级备课前80%的知识点专题课,其它知识点不是造成扣分的主要原因,专题讲了也没啥用,多半是粗心搞的
51 |
52 | ## 3 绘图过程
53 |
54 | 老师怎么备课就轮不到我们操心了,我们只要画出图来就行。
55 |
56 | > 注意:绘图有时不会一次性绘制得很漂亮,所以应当在指定好坐标轴的前提下,一点点去试着绘图,逐渐完善图片的细节。
57 | > 下面的绘图执行细节步骤就是针对本例一点点试出来的。
58 |
59 | ### 3.1 读取原始数据
60 |
61 | 来源:可能是年级数学校验组统计考试扣分情况的表格中提取出来的字典
62 |
63 | 字段:**知识点名称 | 平均扣分值** ,以字典存储
64 |
65 | ### 3.2 绘图数据的准备
66 |
67 | x轴:知识点名称(柱线公共)
68 |
69 | y轴:
70 |
71 | * 柱状图:平均扣分的取值,由左至右必须从大到小排列
72 |
73 | * 折线图:知识点出现的累计占比(当前知识点及其左边知识点柱状图的面积和占柱状图总面积比),纵坐标取值必须是百分数(不含%号)
74 |
75 | ### 3.3 帕累托图的柱状图部分绘制
76 |
77 | 1. x轴是知识点名称xaxis_data,适当倾斜以防止横坐标之间相互遮挡显示不全
78 |
79 | 2. y轴是平均失分的直接数值yaxis_data,图例“扣分”
80 |
81 | 3. 柱状图标题设置为“数学模块最薄弱的失分点”
82 |
83 | 4. 另起空y轴(extend_axis向yaxis依赖注入),用于后续累加的折线图纵轴取值
84 |
85 | ### 3.4 帕累托图的折线图部分绘制
86 |
87 | 1. x轴是知识点名称xaxis_data
88 |
89 | 2. y轴是知识点出现的累计占比(当前知识点及其左边知识点柱状图的面积和占柱状图总面积比,percentList),图例“扣分占比”
90 |
91 | 3. x轴确保和帕累托图的柱状图部分一致
92 |
93 | 4. y轴用帕累托图的柱状图部分之前创建的空y轴(后创建的y轴,yaxis_index为1)
94 |
95 | 5. 线容易被柱子挡住,确保折线图放在比柱状图更高图层的位置(z_level大)
96 |
97 | ### 3.5 合成帕累托图
98 |
99 | 说白了,就是往柱状图上**叠加**(overlap)折线图
100 |
101 | ### 3.6 执行保存
102 |
103 | 由于上一步合成帕累托图的时候,折线图加在了柱状图上,所以保存应该保存柱状图。
104 |
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_2/example3_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Line, Bar
3 | import pyecharts.options as opts
4 |
5 |
6 | """数据来源:可能是年级数学校验组统计考试扣分情况的表格中提取出来的字典
7 |
8 | 字段:知识点名称 | 平均扣分值 ,以字典存储
9 | """
10 | knowledge = {
11 | "圆锥曲线": 7.5,
12 | "直线与圆": 5.0,
13 | "立体几何": 10.1,
14 | "空间向量": 3.2,
15 | "数列": 14.5,
16 | "解三角": 1.9,
17 | "导数": 28.5,
18 | "函数模型": 3.3,
19 | "二项式定理": 3.0,
20 | "线性规划": 4.0,
21 | "平面向量": 3.5,
22 | "复数": 1.3,
23 | "集合": 1.9
24 | }
25 |
26 |
27 | """坐标数据准备1:
28 |
29 | 准备帕累托图的柱状图【数据】部分:
30 | 1、横坐标:知识点名称
31 | 2、纵坐标:平均扣分的取值
32 | 3、帕累托图下的约束:纵坐标由左至右必须从大到小排列
33 | """
34 | # 取出knowledge中的键值对,以值为依据将键值对进行排序(从大到小)后,将键值对以元组的形式存在knowledge_sorted中
35 | knowledge_sorted = sorted(knowledge.items(), key=lambda knowledge_item: knowledge_item[1], reverse=True)
36 |
37 | # 取出x轴数据
38 | xaxis_data = [kn_item[0] for kn_item in knowledge_sorted]
39 | # 取出柱状图的y轴数据
40 | yaxis_data = [kn_item[1] for kn_item in knowledge_sorted]
41 |
42 |
43 | """坐标数据准备2:
44 |
45 | 准备帕累托图的折线图【数据】部分:
46 | 1、横坐标:知识点名称
47 | 2、纵坐标:知识点出现的累计占比(当前知识点及其左边知识点柱状图的面积和占柱状图总面积比)
48 | 3、帕累托图下的约束:纵坐标取值必须是百分数(不含%号)
49 | """
50 | # 定义一个累计频率的空列表percentlist,用yaxis_data的元素初始化
51 | y_line_percentList = [data for data in yaxis_data]
52 | # 计算折线图的y轴数据总和
53 | total_y_data = sum(yaxis_data)
54 | # 添加相应的频率
55 | for index, y_data in enumerate(y_line_percentList[1:], start=1):
56 | # 当前元素 = 当前元素 + 前一个元素
57 | # 与前一个不断累加
58 | y_line_percentList[index] = y_data + y_line_percentList[index - 1]
59 | # 化作百分数形式(保留两位小数)
60 | y_line_percentList = [round(data * 100 / total_y_data, 2) for data in y_line_percentList]
61 | # 解开注释可以控制台验证取值正确性:
62 | # print(percentList)
63 | # print(yaxis_data)
64 |
65 |
66 | """帕累托图的柱状图部分绘制
67 |
68 | 1、x轴是知识点名称xaxis_data,适当倾斜以防止横坐标之间相互遮挡显示不全
69 | 2、y轴是平均失分的直接数值yaxis_data,图例“扣分”
70 | 3、柱状图标题设置为“数学模块最薄弱的失分点”
71 | 4、另起空y轴(extend_axis向yaxis依赖注入),用于后续累加的折线图纵轴取值
72 | """
73 | bar = (
74 | Bar()
75 | .set_global_opts(title_opts=opts.TitleOpts(title="数学模块最薄弱的失分点"),
76 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45))
77 | )
78 | .add_xaxis(xaxis_data=xaxis_data)
79 | .add_yaxis(series_name="扣分", y_axis=yaxis_data)
80 | .extend_axis(yaxis=opts.AxisOpts())
81 | )
82 |
83 |
84 | """帕累托图的折线图部分绘制
85 |
86 | 1、x轴是知识点名称xaxis_data
87 | 2、y轴是知识点出现的累计占比(当前知识点及其左边知识点柱状图的面积和占柱状图总面积比,percentList),图例“扣分占比”
88 | 3、x轴确保和帕累托图的柱状图部分一致
89 | 4、y轴用帕累托图的柱状图部分之前创建的空y轴(后创建的y轴,yaxis_index为1)
90 | 5、线容易被柱子挡住,确保折线图放在比柱状图更高图层的位置(z_level大)
91 | """
92 | line = (
93 | Line()
94 | .add_xaxis(xaxis_data=xaxis_data)
95 | .add_yaxis(series_name="扣分占比", y_axis=y_line_percentList,
96 | yaxis_index=1,
97 | z_level=1)
98 | )
99 |
100 |
101 | """万事俱备,合成帕累托图
102 |
103 | 往柱状图上叠加(overlap)折线图
104 | """
105 | pareto = bar.overlap(line)
106 |
107 | # 保存帕累托图
108 | resultPath = "./result"
109 | if not os.path.exists(path=resultPath):
110 | os.mkdir(path=resultPath)
111 | resultFileName = "math_analysis_pareto.html"
112 |
113 | pareto.render(path=os.path.join(resultPath, resultFileName))
114 | # 等价,但是同一张图不能重复render
115 | # bar.render(path=os.path.join(resultPath, resultFileName))
116 | # 叠加后,折线图和柱状图的变化是相同的
117 | # line.render(path=os.path.join(resultPath, "temp_line.html"))
118 |
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_3/description.md:
--------------------------------------------------------------------------------
1 | # example3_3
2 |
3 | 用途:仅利用菜品营业额,分析哪些菜品易于盈利
4 |
5 | > 分析:可视化的目的是``在原因结果、投入产出关系不够全面了解的情况下,描述和识别最有影响的因子类别``,故采用帕累托图进行绘制。
6 | >
7 | > 说人话意思就是:帕累托图的柱状图部分,可以由高向低排出营业额高的菜品(得出营业额较高的原因主次);
8 | > 而它的折线图部分,则可依据“8-2定律”在较大程度指明,
9 | > 营业额较高的菜品(共占营业额80%)有哪些,这些菜品更应该重视,
10 | > 从而指导餐厅抓主要矛盾,力保人气菜品(前80%),争取冷门菜品(后20%)热度上升或放弃低销售菜品。
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_3/example3_3.py:
--------------------------------------------------------------------------------
1 | from pyecharts.charts import Bar, Line
2 | import pyecharts.options as opts
3 | import os
4 |
5 | """原始数据
6 |
7 | 字段:菜品名 | 年营业额(单位:元)
8 | """
9 | dish_profit = {"番茄鸡蛋": 9900, "避风塘茄夹": 6660, "广东菜心": 5210, "红烧肉": 8880, "土豆烧排骨": 2300,
10 | "木耳炒肉": 1600, "虾仁蒸蛋": 4280, "胡萝卜牛腩": 3460, "水果沙拉": 1800, "狮子头": 3200}
11 |
12 | """准备公共x轴和柱状图、折线图分别的y轴
13 | """
14 | # 键值对按值排序
15 | dish_profit_sorted = sorted(dish_profit.items(), key=lambda x: x[1], reverse=True)
16 |
17 | # 公共x轴数据
18 | xaxisData = [data for (data, _) in dish_profit_sorted]
19 | # 柱状图y轴数据
20 | yaxisBar = [data for (_, data) in dish_profit_sorted]
21 |
22 | # 计算折线图y轴所需数据(用yaxisBar初始化)
23 | yaxisLine = [data for data in yaxisBar]
24 | # y轴项目总和
25 | sumYData = sum(yaxisBar)
26 | # 求出折线图y轴下的值(百分数,无百分号形式,保留两位小数)
27 | for index, y_data in enumerate(yaxisLine[1:], start=1):
28 | yaxisLine[index] = y_data + yaxisLine[index - 1]
29 | yaxisLine = [round(y_data / sumYData * 100, 2) for y_data in yaxisLine]
30 | # print(yaxisLine)
31 |
32 |
33 | """执行绘图
34 |
35 | 1. 将菜品名字作为x轴;
36 | 2. 菜品盈利额作为y轴,绘制柱状图,图例设置为”盈利额“;
37 | 3. 计算各个菜品的盈利占总盈利额的比例,作为y轴绘制折线图,图例设置为"盈利占比(%)";
38 | 4. x轴的标签旋转45度,防遮挡;
39 | 5. 整个表的标题设置为“各菜品盈利额”;
40 | 6. 将折线图叠加(overlap)在柱状图上。
41 | 7. 将图表保存
42 | 8. y轴取值均只保留2位小数
43 | 9. 折线图y轴在柱状图y轴图层之上,防止柱子遮挡折线
44 | """
45 | # 保存路径
46 | resultPath = "./result"
47 | if not os.path.exists(resultPath):
48 | os.mkdir(path=resultPath)
49 | # 保存文件名
50 | resultFileName = "restaurant_pareto.html"
51 | # 执行绘图并保存
52 | pareto = (
53 | Bar()
54 | .set_global_opts(xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45)),
55 | title_opts=opts.TitleOpts(title="各菜品盈利额"))
56 | .add_xaxis(xaxis_data=xaxisData)
57 | .add_yaxis(series_name="盈利额", y_axis=yaxisBar)
58 | .extend_axis(yaxis=opts.AxisOpts()) # 新y轴:index为1
59 | .overlap(
60 | chart=(
61 | Line()
62 | .add_xaxis(xaxis_data=xaxisData)
63 | .add_yaxis(series_name="盈利占比(%)", y_axis=yaxisLine, yaxis_index=1, z_level=1)
64 | )
65 | )
66 | .render(path=os.path.join(resultPath, resultFileName))
67 | )
68 |
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_4/description.md:
--------------------------------------------------------------------------------
1 | # example3_4
2 |
3 | 用途:信用卡公司发现最近有一大批客户的信用卡无法激活,调查后发现有若干原因导致了这些现象,现在需要找出主要原因优先处理。
4 |
5 | > 分析:可视化的目的是``在原因结果、投入产出关系不够全面了解的情况下,描述和识别最有影响的因子类别``,故采用帕累托图进行绘制。
6 | >
7 | > 说人话意思就是:哪些原因是造成信用卡无法激活问题的主要问题(柱状图说明)?短期内优先处理哪些问题可以抓住主要矛盾,最快解决绝大多数问题(折线图说明)。
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/example3_4/example3_4.py:
--------------------------------------------------------------------------------
1 | from pyecharts.charts import Bar, Line
2 | import pyecharts.options as opts
3 | import os
4 |
5 |
6 | """原始数据
7 |
8 | 字段:错误类型 | 近一周出现次数
9 | """
10 | causes_statistics = {
11 | "名字拼写错误": 27,
12 | "地址错误": 16,
13 | "电话号码错误": 12,
14 | "邮箱错误": 9,
15 | "验证码错误": 3
16 | }
17 |
18 |
19 | """提取坐标轴数据
20 |
21 | x轴:错误类型(柱线公共)
22 | 柱状图y轴:x轴对应直接数据,自左向右由大到小。图例“原因”
23 | 折线图y轴:当前字段及其前柱子面积占比之和。图例“原因占比(%)”
24 | """
25 | # 预备:将原始数据键值对按值自大到小排序
26 | causes_statistics_sorted = sorted(causes_statistics.items(),
27 | key=lambda cause: cause[1], reverse=True)
28 | # 输出一下证明它是列表
29 | # print(causes_statistics_sorted)
30 | # 提取公共x轴
31 | x_data = [xData for xData, _ in causes_statistics_sorted]
32 | # 提取柱状图y轴
33 | y_data_bar = [yDataBar for _, yDataBar in causes_statistics_sorted]
34 |
35 | # y轴数据总和
36 | yTotal = sum(y_data_bar)
37 | # 提取折线图y轴(不能直接用y_data_bar赋值柱状图存的原y轴数据,避免浅复制)
38 | y_data_line = list(y_data_bar)
39 | # 计算前所有字段面积占比(百分值去%符号),保留两位小数
40 | for index, y_data in enumerate(y_data_line[1:], start=1):
41 | y_data_line[index] = y_data + y_data_line[index - 1]
42 | y_data_line = [round(y_data*100/yTotal, 2) for y_data in y_data_line]
43 |
44 |
45 | """绘制帕累托图
46 |
47 | 1. 将未激活原因作为x轴;
48 | 2. 将未激活数量作为y轴,绘制柱状图;
49 | 3. 将柱状图的图例设置为原因,将柱状图的透明度(opacity,用法查pyecharts官方文档)设置为0.5,以防止遮挡折线图部分;
50 | 4. 将整个图表的标题设置为:信用卡未激活的原因;
51 | 5. 另起y轴,将累计频率作为y轴,绘制折线图,将折线图的图例设置为"原因占比(%)";
52 | 6. 将折线图叠加在柱状图上。
53 | 7. 将文件保存
54 | """
55 | # 保存路径
56 | resultPath = "./result"
57 | if not os.path.exists(path=resultPath):
58 | os.mkdir(path=resultPath)
59 | # 保存文件名
60 | resultFileName = "credit_company_pareto.html"
61 | # 执行绘图
62 | pareto = (
63 | Bar()
64 | .set_global_opts(title_opts=opts.TitleOpts(title="信用卡未激活的原因"))
65 | .add_xaxis(xaxis_data=x_data)
66 | .add_yaxis(series_name="原因", y_axis=y_data_bar, yaxis_index=0,
67 | itemstyle_opts=opts.ItemStyleOpts(opacity=0.5))
68 | .extend_axis(yaxis=opts.AxisOpts()) # 添加新的空y轴,index为1
69 | .overlap(chart=(
70 | Line()
71 | .add_xaxis(xaxis_data=x_data)
72 | .add_yaxis(series_name="原因占比(%)", y_axis=y_data_line,
73 | yaxis_index=1)
74 | ))
75 | .render(path=os.path.join(resultPath, resultFileName))
76 | )
--------------------------------------------------------------------------------
/03柱线叠加图/03-2主因分析之帕累托图/whatisParetoChart.md:
--------------------------------------------------------------------------------
1 | # 帕累托图(Pareto Chart)
2 |
3 | ## 1 什么是帕累托图
4 |
5 | 帕累托图的本质是**一个柱状图和一个折线图的叠加**,二者共x轴,分别使用不同的y轴。
6 |
7 | * 柱状图部分的y轴:x轴字段对应的直接数据。且帕累托图绘制时要求从左到右**y轴必须自大到小排列下来**
8 | (当然y轴讲顺序x轴也会对应上的......)
9 |
10 | * 折线图部分的y轴:x轴当前字段,**加上当前字段之前所有字段**,的柱状图的**面积占比**,
11 | 所以由此可以发现,折线图在帕累托图中**始终是向上趋势,且上升到最后一个x轴字段的时候值一定是100%**
12 |
13 | ## 2 数学含义
14 |
15 | * 柱状图的含义:y轴从大到小排开,能够表现出x轴字段的**优先情况(重要性)**
16 |
17 | * 折线图的含义:反映出x轴字段代表的事件在依照优先次序处理的情况下**完成的进度**
18 |
19 | ## 3 指导意义
20 |
21 | 结合**80-20原则**,折线图80%处经过的x轴字段,重要性往往较高(柱状图直接取值很大),
22 | 在条件有限的情况下,先处理掉前80%的内容,可以在**控制成本的条件下尽快抓住问题主要矛盾着手应对**,提升效率。
--------------------------------------------------------------------------------
/04构成和差异之堆叠柱状图/04-1构成和差异结合分析/example4_1/example4_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Bar
3 | import pyecharts.options as opts
4 |
5 |
6 | """原始数据:2020下半年部分商品销售额变化表
7 |
8 | 下半年一共跟踪了choc(olate)、gum和walnut的销售情况(单位:元)
9 | 接下来分析销售额的组成和比较不同月份各各产品销售情况的差异
10 | """
11 | # 设置列表
12 | months = ["7月", "8月", "9月", "10月", "11月", "12月"]
13 | choc_sales = [5340, 6078, 6460, 6475, 7431, 8038]
14 | gum_sales = [4340, 4379, 4460, 5075, 5431, 6038]
15 | walnut_sales = [6340, 5579, 4460, 4075, 3431, 3038]
16 |
17 |
18 | """执行绘图
19 |
20 | 1、采取直接数据的堆叠方式展现(同一个x轴下的数据在同一个stack展示)
21 | 2、x轴:月份
22 | 3、y轴:产品对应月份销售额。图例分别是:巧克力、口香糖、核桃
23 | 4、整个图表的标题:2020下半年商品销售额变化
24 | 5、堆叠:指定y轴数据在同一个stack(怎么搞的去查pyecharts官方文档)
25 | 6、避免数据遮挡:柱子堆叠的时候,底下柱子的数值label会被上面的柱子遮挡,
26 | 这是可以设置数值label显示在自己的柱子中间(怎么搞的去查pyecharts官方文档)
27 | """
28 | # 创建Bar对象,赋值给变量bar
29 | stacked_bar = (
30 | Bar()
31 | .set_global_opts(title_opts=opts.TitleOpts(title="2020下半年商品销售额变化"))
32 | .add_xaxis(xaxis_data=months)
33 | .add_yaxis(
34 | series_name="巧克力",
35 | y_axis=choc_sales,
36 | stack="sales",
37 | label_opts=opts.LabelOpts(position="inside")
38 | )
39 | .add_yaxis(
40 | series_name="口香糖",
41 | y_axis=gum_sales,
42 | stack="sales", # stack同名就堆叠一个柱子上
43 | label_opts=opts.LabelOpts(position="inside")
44 | )
45 | .add_yaxis(
46 | series_name="核桃",
47 | y_axis=walnut_sales,
48 | stack="sales",
49 | label_opts=opts.LabelOpts(position="inside")
50 | )
51 | )
52 |
53 |
54 | # 使用render函数将堆积柱状图保存在指定路径
55 | resultPath = "./result"
56 | if not os.path.exists(path=resultPath):
57 | os.mkdir(path=resultPath)
58 | resultFileName = "sales_stacked_bar.html"
59 |
60 | stacked_bar.render(path=os.path.join(resultPath, resultFileName))
61 |
--------------------------------------------------------------------------------
/04构成和差异之堆叠柱状图/04-1构成和差异结合分析/example4_2/example4_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Bar
3 | import pyecharts.options as opts
4 |
5 | """准备数据:2020年1-3季度GDP(单位:亿元)
6 | """
7 | # 创建变量x_data储存季度名称,作为x轴的数据
8 | x_data = ["第一季度", "第二季度", "第三季度"]
9 | # 将每个产业的每个季度的生产值保存在一个字典中
10 | data = {
11 | "第一产业": [8014.7, 13992.8, 20528.5],
12 | "第二产业": [67968.9, 93094.8, 94684.4],
13 | "第三产业": [107685.8, 118408.4, 123963.2]
14 | }
15 |
16 | """执行堆叠柱状图绘制
17 |
18 | 1. x轴设置为列表x_data。
19 | 2. 逐个添加y轴数据data
20 | 图例设置为字典的key,取值为key中对应的value
21 | 堆积名称stack统一设置为"GDP",
22 | 数据标签的位置设置为内部居中(inside)。
23 | 3. 图表标题为"2020年1-3季度GDP(单位:亿元)"
24 | 4. 将图表保存。
25 | """
26 | stacked_bar = (
27 | Bar()
28 | .set_global_opts(title_opts=opts.TitleOpts(title="2020年1-3季度GDP(单位:亿元)"))
29 | .add_xaxis(xaxis_data=x_data)
30 | )
31 | # 循环添加y轴数据
32 | for key, value in data.items():
33 | stacked_bar.add_yaxis(
34 | series_name=key,
35 | y_axis=value,
36 | stack="GDP",
37 | label_opts=opts.LabelOpts(position="inside")
38 | )
39 | # 保存路径和文件名
40 | resultPath = "./result"
41 | if not os.path.exists(path=resultPath):
42 | os.mkdir(path=resultPath)
43 | resultFileName = "GDP_stacked_bar.html"
44 |
45 | stacked_bar.render(path=os.path.join(resultPath, resultFileName))
46 |
--------------------------------------------------------------------------------
/04构成和差异之堆叠柱状图/04-1构成和差异结合分析/example4_3/example4_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Bar
3 | import pyecharts.options as opts
4 |
5 | """准备数据:一年来商品的销售
6 |
7 | walnut_sales可能是下半年引入的新品
8 | 前半年无数据部分用"-"填充空位,确保x轴和y轴对得上位
9 | """
10 | # 月份
11 | months = [f"{mon}月" for mon in range(1, 13)]
12 | # 各种商品的销售额
13 | choc_sales = [2045, 2580, 2789, 3455, 3256, 3678, 5340, 6078, 6460, 6475, 7431, 8038]
14 | gum_sales = [1234, 1467, 1754, 2354, 2897, 3487, 4340, 4379, 4460, 5075, 5431, 6038]
15 | walnut_sales = ["-", "-", "-", "-", "-", "-", 6340, 5579, 4460, 4075, 3431, 3038]
16 |
17 | """执行堆叠柱状图绘制和保存
18 |
19 | 1、各月各商品销售额堆积图中:
20 | 第一层为巧克力的销售额。
21 | 第二层为口香糖的销售额。
22 | 第三层为核桃的销售额。
23 | 2、x轴是月份
24 | 3、y轴是各种销售额,图例分别为巧克力、口香糖、核桃,采用堆叠方式,堆叠stack统一命名为sales
25 | 4、数值label要防止被遮挡,显示在柱子中间
26 | 5、1~6月部分新品还没有数据,用"-"顶替数据缺项
27 | 6、整张图的标题是“2020全年商品销售额变化”
28 | 7、考虑到x轴真的太!!!多!!!了!!!
29 | 显示的时候考虑把x轴和y轴翻转(reversal)一下(横过来),不然图像太长了......
30 | """
31 | # 保存路径
32 | resultPath = "./result"
33 | if not os.path.exists(path=resultPath):
34 | os.mkdir(path=resultPath)
35 | # 保存文件名
36 | resultFileName = "sales_annual_stacked_bar.html"
37 | # 绘图
38 | stacked_bar = (
39 | Bar()
40 | .set_global_opts(title_opts=opts.TitleOpts(title="2020全年商品销售额变化"))
41 | .add_xaxis(xaxis_data=months)
42 | .add_yaxis(
43 | series_name="巧克力",
44 | y_axis=choc_sales,
45 | stack="sales", # 先加y轴的堆叠在底下,后加y轴的堆叠在上面
46 | label_opts=opts.LabelOpts(position="inside")
47 | )
48 | .add_yaxis(
49 | series_name="口香糖",
50 | y_axis=gum_sales,
51 | stack="sales",
52 | label_opts=opts.LabelOpts(position="inside")
53 | ).add_yaxis(
54 | series_name="核桃",
55 | y_axis=walnut_sales,
56 | stack="sales",
57 | label_opts=opts.LabelOpts(position="inside")
58 | )
59 | .reversal_axis() # xy轴翻转,把图表横过来
60 | .render(path=os.path.join(resultPath, resultFileName))
61 | )
62 |
--------------------------------------------------------------------------------
/04构成和差异之堆叠柱状图/04-2变化量分析之瀑布图/example4_4/example4_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Bar
3 | import pyecharts.options as opts
4 |
5 | """原数据:个体商户12个月的资金流动情况
6 |
7 | 利用瀑布图表达出每个月的盈亏变化
8 | """
9 | x_data = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
10 | # 当月资金流动情况(+盈利,-亏损)
11 | alter_data = [4000, 3450, 2850, -1800, -1500, 9000, 1300, 1000, 2100, -1000, -4200, -1510]
12 | # 年初总资金
13 | beginTotal = 5000
14 | # 年末剩余总资金
15 | endTotal = 18690
16 |
17 | """准备瀑布图数据
18 |
19 | 增加年初值和年末余值单独表示,用一组单独的柱子表示(体现不同的颜色)
20 | 中间1~12月份的数据全部用“变化量”表示(+盈-亏),变化取值悬浮于半空中,体现总值的大致走向
21 | 体现“柱子漂浮”的现象,需要柱子下方有“打底”的白色柱子垫着
22 | 打底柱子上方,放当月盈利值或者亏损值(需要创建盈利柱子和亏损柱子数据分开讨论,这样最终画出来,不同颜色的柱子区分能区分盈利和亏损)
23 | 打底柱子当月取值:当月总额-盈利值(如果是盈利)或者当月总额(如果是亏损)
24 | 所以打底柱子想求出来,先要把各个月当月总额求出来
25 | """
26 | # 扩展x轴,增加年初值和年末余值两项
27 | x_data.insert(0, "年初值")
28 | x_data.append("年末余值")
29 |
30 | # 增加的两项对应值单独创建一组y轴,区分颜色
31 | total_data = ["-"] * len(x_data)
32 | total_data[0] = beginTotal
33 | total_data[-1] = endTotal
34 |
35 | # 盈利提取数据y轴对应项(注意两端缺项) ["-"] * 14
36 | y_profit_extracted_data = ["-"] * len(x_data)
37 | # 亏损提取数据y轴对应项(注意两端缺项) ["-"] * 14
38 | y_loss_extracted_data = ["-"] * len(x_data)
39 | # 放盈利/亏损提取数据两种情景的柱子,下标从1开始(跳过头部的缺项)
40 | for extracted_index, alter_item in enumerate(alter_data, start=1):
41 | if alter_item > 0:
42 | y_profit_extracted_data[extracted_index] = alter_item
43 | elif alter_item < 0:
44 | # 负数取相反数
45 | y_loss_extracted_data[extracted_index] = -alter_item
46 | # else,即alter_item == 0:保持缺项
47 |
48 | # 打底柱子取值的计算(两端缺项) ["-"] * 14
49 | base_data = ["-"] * len(x_data)
50 | # 辅助计算使用:存放当月变化后的总收入(月末) ["-"] * 12
51 | temp_total_data = ["-"] * len(alter_data)
52 | temp_total_data[0] = beginTotal + alter_data[0]
53 | for index, alter_item in enumerate(alter_data[1:], start=1):
54 | temp_total_data[index] = temp_total_data[index - 1] + alter_item
55 | # 计算base_data
56 | for index, alter_item in enumerate(alter_data):
57 | if alter_item > 0:
58 | base_data[index + 1] = temp_total_data[index] - alter_item
59 | elif alter_item < 0:
60 | base_data[index + 1] = temp_total_data[index]
61 | else: # alter_item == 0
62 | base_data[index] = "-"
63 | print(base_data)
64 |
65 | """绘制瀑布图
66 |
67 | - 图例统一设置为空,堆叠stack统一为"waterfall_plot"
68 | - 打底柱子颜色设置为白色;
69 | - 其它x轴和y轴按照顺序进行叠加即可,盈利和亏损的悬浮柱子要设置图例,分别为“盈利”“亏损”
70 | - 设置图片标题为"全年每月收入与支出";注意避免横坐标丢失。
71 | - 将瀑布图保存
72 | """
73 | # 保存路径
74 | resultPath = "./result"
75 | if not os.path.exists(path=resultPath):
76 | os.mkdir(path=resultPath)
77 | # 保存文件名
78 | resultFileName = "in_out_waterfall_stacked_bar.html"
79 |
80 | waterfall_stacked_bar = (
81 | Bar()
82 | .set_global_opts(
83 | title_opts=opts.TitleOpts(title="下半年每月收入与支出"),
84 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=45))
85 | )
86 | .add_xaxis(
87 | xaxis_data=x_data,
88 | )
89 | .add_yaxis(
90 | series_name="",
91 | y_axis=base_data,
92 | color="white",
93 | stack="waterfall_plot",
94 | # 隐藏起来打底的柱子
95 | label_opts=opts.LabelOpts(is_show=False),
96 | tooltip_opts=opts.TooltipOpts(is_show=False)
97 | )
98 | .add_yaxis(
99 | series_name="",
100 | y_axis=total_data,
101 | stack="waterfall_plot"
102 | )
103 | .add_yaxis(
104 | series_name="盈利",
105 | y_axis=y_profit_extracted_data,
106 | stack="waterfall_plot"
107 | )
108 | .add_yaxis(
109 | series_name="亏损",
110 | y_axis=y_loss_extracted_data,
111 | stack="waterfall_plot"
112 | )
113 | .render(path=os.path.join(resultPath, resultFileName))
114 | )
--------------------------------------------------------------------------------
/04构成和差异之堆叠柱状图/04-2变化量分析之瀑布图/whatisWaterfallPlot.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/04构成和差异之堆叠柱状图/04-2变化量分析之瀑布图/whatisWaterfallPlot.md
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-1普通饼状图/example5_1/example5_1.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/05构成和差异之饼状图/05-1普通饼状图/example5_1/example5_1.py
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-2环状图、南丁格尔玫瑰图/example5_2/example5_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Pie
3 | import pyecharts.options as opts
4 |
5 | """准备原始数据:IT网站各分区下的访问量
6 |
7 | 略去读文件过程,读取结果如下:
8 | """
9 | # 绘制饼状图,数据项及其取值按照一个个元组进行组合
10 | user_data = [('深度学习', 1000), ('数据分析', 700), ('Web开发', 500), ('爬虫开发', 350),
11 | ('图像处理', 250), ('机器学习', 220), ('数据挖掘', 200), ('人工智能', 180),
12 | ('自然语言处理', 160), ('游戏开发', 140), ('数据库开发', 120), ('可视化工程', 832)]
13 | # 预处理:依照值将user_data从大到小排个序,后面显示会更漂亮
14 | user_data.sort(key=lambda data_item: data_item[1], reverse=True)
15 |
16 |
17 | """执行绘图
18 |
19 | 1. 将列表中的元组按照元组中的第二个数的大小,也就是阅读量的大小,从大到小排序。
20 | 2. 设置数据标签的格式为“图例: 占比”(占比在显示时要带上百分号),(怎样设置格式formatter去查pyecharts官方文档)
21 | 3. 设置按照玫瑰图的方式显示,且圆心角相同,数值大小通过每一块饼的大小直观比对(这一步需要查pyecharts官方文档)。
22 | 4. 设置图表的标题为"阅读量统计”。
23 | 5. 适当调整图表中一些元素的位置,避免遮挡、排版凌乱等问题
24 | 6. 生成图表,保存
25 | """
26 | # 保存路径
27 | resultPath = "./result"
28 | if not os.path.exists(path=resultPath):
29 | os.mkdir(path=resultPath)
30 | # 保存文件名
31 | resultFileName = "web_visit_rose_pie.html"
32 |
33 | rose_pie = (
34 | Pie()
35 | .set_global_opts(
36 | title_opts=opts.TitleOpts(title="阅读量统计", subtitle="技术专栏模块"),
37 | # 图例位置默认会遮挡标题,下面这样的调整是不断试错找出的布局方式
38 | legend_opts=opts.LegendOpts(
39 | pos_left="1%",
40 | pos_top="60%",
41 | orient="vertical",
42 | type_="scroll"
43 | )
44 | )
45 | .add(
46 | series_name="用户数据",
47 | data_pair=user_data,
48 | label_opts=opts.LabelOpts(
49 | # {b}和{d}表示图例名称和占比数值(不带百分号),这一步控制每一块饼旁边显示的东西是什么,具体地可以查文档
50 | formatter="{b}: {d}%"
51 | ),
52 | rosetype="area" # 圆心角相同,数据差别靠每一块饼的半径凸显出来
53 | )
54 | .render(path=os.path.join(resultPath, resultFileName))
55 | )
56 |
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-2环状图、南丁格尔玫瑰图/example5_2/result/web_visit_rose_pie.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
177 |
178 |
179 |
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-2环状图、南丁格尔玫瑰图/example5_3/example5_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Pie
3 | import pyecharts.options as opts
4 |
5 | """原数据:某连锁店开通会员的人群所在地区分布
6 |
7 | 键值对:地区名 | 人数(单位;人)
8 | """
9 | data = {
10 | '北京': 78, '上海': 77, '黑龙江': 60, '吉林': 75, '辽宁': 91, '贵州': 93, '新疆': 82, '西藏': 61, '青海': 62,
11 | '四川': 40, '云南': 58, '陕西': 24, '重庆': 77, '内蒙古': 53, '广西': 46, '海南': 92, '澳门': 55, '湖南': 72,
12 | '江西': 65, '福建': 57, '安徽': 36, '浙江': 77, '江苏': 48, '宁夏': 32, '山西': 70, '河北': 86, '天津': 94
13 | }
14 | # 附带配色方案(生成图案顺时针依次显示的颜色)
15 | color_series = ['#FAE927', '#E9E416', '#C9DA36', '#9ECB3C', '#6DBC49',
16 | '#37B44E', '#3DBA78', '#14ADCF', '#209AC9', '#1E91CA',
17 | '#2C6BA0', '#2B55A1', '#2D3D8E', '#44388E', '#6A368B',
18 | '#7D3990', '#A63F98', '#C31C88', '#D52178', '#D5225B',
19 | '#D02C2A', '#D44C2D', '#F57A34', '#FA8F2F', '#D99D21',
20 | '#CF7B25', '#CF7B25', '#CF7B25']
21 | # 预处理:将原数据按照从大到小取值的顺序排序,生成用于绘图的标签-数值元组
22 | data_sorted = sorted(data.items(), key=lambda data_item: data_item[1], reverse=True)
23 |
24 |
25 | """绘图南丁格尔玫瑰图
26 |
27 | 数据的系列名称(series_name)统一为“会员地区分布”
28 | 按照给定的配色方案给每块饼配色
29 | 绘制为南丁格尔环状玫瑰图
30 | 设置玫瑰图类型(rosetype)圆心角相同,数据差异仅通过半径给出
31 | 环的内半径(radius)为画布尺寸(长宽较小者)的30%,环的最大外半径(radius)(数值最大的饼的外径)为画布的100%
32 | 每块饼的标签(label)显示在饼的内部,字号为8,标签显示格式为"{数据项名}:{直接数值}人"
33 | 图例(legend)不显示
34 | 整张图标题设为“会员地区分布”
35 | 保存图表
36 | """
37 | # 保存路径
38 | resultPath = "./result"
39 | if not os.path.exists(path=resultPath):
40 | os.mkdir(path=resultPath)
41 | # 文件名
42 | resultFileName = "vip_rose_pie.html"
43 | # 执行绘图
44 | rose_pie = (
45 | Pie()
46 | .set_global_opts(
47 | title_opts=opts.TitleOpts(title="会员地区分布"),
48 | legend_opts=opts.LegendOpts(is_show=False)
49 | )
50 | .set_colors(colors=color_series)
51 | .add(
52 | series_name="会员地区分布",
53 | data_pair=data_sorted,
54 | rosetype="area",
55 | radius=("30%", "100%"),
56 | label_opts=opts.LabelOpts(
57 | position="inside",
58 | font_size=8,
59 | formatter="{b}:{c}人"
60 | )
61 | )
62 | .render(path=os.path.join(resultPath, resultFileName))
63 | )
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-2环状图、南丁格尔玫瑰图/example5_4/example5_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Pie
3 | from pyecharts import options as opts
4 |
5 | """原始数据:两场网络直播带货中,不同产品的销量情况
6 |
7 | 数据:(产品名称, 销量)
8 | """
9 | liveCommerceOne = [("衬衫", 111), ("羊毛衫", 122), ("雪纺衫", 113), ("裤子", 210), ("高跟鞋", 170), ("袜子", 109)]
10 | liveCommerceTwo = [("衬衫", 139), ("羊毛衫", 241), ("雪纺衫", 325), ("裤子", 260), ("高跟鞋", 210), ("袜子", 335)]
11 |
12 |
13 | """绘制多个南丁格尔玫瑰图(一共2个图表)
14 |
15 | 整个图表标题设为“网络直播带货销量对比”
16 | 图例系列名(series_name)均设为空
17 | 玫瑰图最大外径为绘图区(长宽小者)的60%,内径为绘图区的20%
18 | 玫瑰图类型设置为圆心角相同,数据大小仅通过
19 | 图1位置(即圆心位置)在绘图区的(25%, 50%)处(相对绘图区水平的25%和竖直的50%处)
20 | 图2位置(即圆心位置)在绘图区的(75%, 50%)处
21 | 数据标签(label)放在每一块饼的内部显示,格式为"{百分比取值}%"
22 | """
23 | # 保存路径
24 | resultPath = "./result"
25 | if not os.path.exists(path=resultPath):
26 | os.mkdir(path=resultPath)
27 | # 保存文件名
28 | resultFileName = "live_commerce_rose_pie.html"
29 | # 执行绘图
30 | rose_pie = (
31 | Pie()
32 | .set_global_opts(title_opts=opts.TitleOpts(title="网络直播带货销量对比"))
33 | .add(
34 | series_name="",
35 | data_pair=liveCommerceOne,
36 | rosetype="area",
37 | radius=("20%", "60%"),
38 | center=("25%", "50%"),
39 | label_opts=opts.LabelOpts(
40 | position="inside",
41 | formatter="{d}%"
42 | )
43 | )
44 | .add(
45 | series_name="",
46 | data_pair=liveCommerceTwo,
47 | rosetype="area",
48 | radius=("20%", "60%"),
49 | center=("75%", "50%"),
50 | label_opts=opts.LabelOpts(
51 | position="inside",
52 | formatter="{d}%"
53 | )
54 | )
55 | .render(path=os.path.join(resultPath, resultFileName))
56 | )
57 |
--------------------------------------------------------------------------------
/05构成和差异之饼状图/05-2环状图、南丁格尔玫瑰图/example5_4/result/live_commerce_rose_pie.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
186 |
187 |
188 |
--------------------------------------------------------------------------------
/05构成和差异之饼状图/whatisPieChart.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/05构成和差异之饼状图/whatisPieChart.md
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-1openpyxl读取excel数据演示/example6_1/example6_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 |
6 | """读取数据"""
7 | # 资源文件统一所在路径
8 | resourcesPath = "./resources"
9 | # 数据文件名
10 | salesPath = "table.xlsx"
11 | # 读文件(工作簿)
12 | salesBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, salesPath)) # type: Workbook
13 | # 选择工作表
14 | fruitSalesSheet = salesBook["水果销量"] # type: Worksheet
15 | # 跳过表头,逐行读取数据
16 | for rowContent in fruitSalesSheet.iter_rows(min_row=2, values_only=True):
17 | # 以列表形式输出
18 | print(list(rowContent))
19 |
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-1openpyxl读取excel数据演示/example6_1/resources/table.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/06别把数据直接放程序里之使用openpyxl/06-1openpyxl读取excel数据演示/example6_1/resources/table.xlsx
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_2/example6_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Line
6 | import pyecharts.options as opts
7 |
8 | """指定基础配置值
9 |
10 | 所有路径配置相关的值放在单独的配置文件,或者这里为了方便就放最前面
11 | """
12 | # 数据资源统一路径
13 | resourcesPath = "./resources"
14 | # 数据资源文件名
15 | resourcesFileName = "table.xlsx"
16 | # 数据所在工作表
17 | colaSheetName = "销量"
18 |
19 | # 保存路径
20 | resultPath = "./result"
21 | if not os.path.exists(path=resultPath):
22 | os.mkdir(path=resultPath)
23 | # 保存文件名
24 | resultFileName = "sales_line.html"
25 |
26 | """获取数据:不同的可乐在1年内的月销量变化
27 |
28 | x轴:月份
29 | y轴:月销量,图例是相应类型可乐的名字
30 | """
31 |
32 |
33 | def read_rows(filename="./", sheetname="Sheet") -> list:
34 | """
35 | 从excel文档中读出所有行,每一行都是列表,所有行存入一个大列表,返回出去
36 | 读取时,不做清洗,只是忠诚地把文件里的数据转移出来到列表里
37 | :param filename: excel文件名(完整路径)
38 | :param sheetname: 工作表Worksheet名
39 | :return: list
40 | """
41 | # 加载文件+选表 两步合并
42 | colaSheet = openpyxl.load_workbook(filename=filename)[sheetname] # type: Worksheet
43 | # 读出所有行数据
44 | rowData = [list(rowContent) for rowContent in colaSheet.iter_rows(values_only=True)]
45 | return rowData
46 |
47 |
48 | # 读出表格数据
49 | rowData = read_rows(filename=os.path.join(resourcesPath, resourcesFileName), sheetname=colaSheetName)
50 | # 取出x轴数据(表头,注意第一列空的,要砍掉)
51 | x_data = rowData[0][1:]
52 | # 取出y轴数据(第2行开始)
53 | y_data = dict()
54 | for rowItem in rowData[1:]:
55 | # eval函数剥开字符串两侧引号,避免字符串数值,适当过滤一下填入数据时候出现的两端空白
56 | y_data[rowItem[0]] = [eval(str(item).strip()) for item in rowItem[1:]]
57 |
58 |
59 | """绘制多y轴折线图
60 |
61 | 1. 读取文档的月份作为x轴,一共有1~12个月;
62 | 2. 读取文档中的数据将商品销量作为y轴,绘制折线图 ;
63 | 3. 图例设置为对应行的商品名称;
64 | 4. 将整个图表标题设置为:增长趋势的比较 ;
65 | 5. 将文件保存
66 | """
67 | line = (
68 | Line()
69 | .set_global_opts(title_opts=opts.TitleOpts(title="增长趋势的比较"))
70 | .add_xaxis(xaxis_data=x_data)
71 | )
72 | for yaxis_series, yaxis_data in y_data.items():
73 | line.add_yaxis(series_name=yaxis_series, y_axis=yaxis_data)
74 | line.render(path=os.path.join(resultPath, resultFileName))
75 |
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_2/resources/table.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_2/resources/table.xlsx
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_3/example6_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Bar
6 | import pyecharts.options as opts
7 |
8 | """指定基础配置值
9 |
10 | 所有路径配置相关的值放在单独的配置文件,或者这里为了方便就放最前面
11 | """
12 | # 数据资源统一路径
13 | resourcesPath = "./resources"
14 | # 数据资源文件名
15 | resourcesFileName = "核桃销量.xlsx"
16 | # 数据所在工作表
17 | yearSheetName = "2020年"
18 |
19 | # 保存路径
20 | resultPath = "./result"
21 | if not os.path.exists(path=resultPath):
22 | os.mkdir(path=resultPath)
23 | # 保存文件名
24 | resultFileName = "nut_sales_line.html"
25 |
26 | """获取数据:不同的商品在1年内的月销量变化
27 |
28 | x轴:月份
29 | y轴:月销量,图例是相应类型商品的名字
30 | """
31 |
32 |
33 | def read_rows(filename="./", sheetname="Sheet") -> list:
34 | """
35 | 从excel文档中读出所有行,每一行都是列表,所有行存入一个大列表,返回出去
36 | 读取时,不做清洗,只是忠诚地把文件里的数据转移出来到列表里
37 | :param filename: excel文件名(完整路径)
38 | :param sheetname: 工作表Worksheet名
39 | :return: list
40 | """
41 | # 加载文件+选表 两步合并
42 | colaSheet = openpyxl.load_workbook(filename=filename)[sheetname] # type: Worksheet
43 | # 读出所有行数据
44 | rowData = [list(rowContent) for rowContent in colaSheet.iter_rows(values_only=True)]
45 | return rowData
46 |
47 |
48 | # 读出表格数据
49 | rowData = read_rows(filename=os.path.join(resourcesPath, resourcesFileName), sheetname=yearSheetName)
50 | # 取出x轴数据(表头,注意第一列空的,要砍掉)
51 | x_data = rowData[0][1:]
52 | # 取出y轴数据(第2行开始)
53 | y_data = dict()
54 | for rowItem in rowData[1:]:
55 | # eval函数剥开字符串两侧引号(防止单元格含字符串),避免字符串数值,适当过滤一下填入数据时候出现的两端空白
56 | y_data[rowItem[0]] = [eval(str(item).strip()) for item in rowItem[1:]]
57 |
58 |
59 | """绘制多y轴折线图
60 |
61 | - 绘制堆叠柱状图,堆叠名称统一为"sales";
62 | - 图例设置为对应商品的名称;
63 | - 数据标签设置为柱子内居中 ;
64 | - 将整个文档标题设置为"2020年商品销售额变化"
65 | - 将文档保存
66 | """
67 | stacked_bar = (
68 | Bar()
69 | .set_global_opts(title_opts=opts.TitleOpts(title="2020年商品销售额变化"))
70 | .add_xaxis(xaxis_data=x_data)
71 | )
72 | for yaxis_series, yaxis_data in y_data.items():
73 | stacked_bar.add_yaxis(
74 | series_name=yaxis_series,
75 | y_axis=yaxis_data,
76 | stack="sales",
77 | label_opts=opts.LabelOpts(position="inside")
78 | )
79 | stacked_bar.render(path=os.path.join(resultPath, resultFileName))
80 |
--------------------------------------------------------------------------------
/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_3/resources/核桃销量.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/06别把数据直接放程序里之使用openpyxl/06-2openpyxl结合可视化演示/example6_3/resources/核桃销量.xlsx
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_1/example7_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Funnel
3 | import pyecharts.options as opts
4 |
5 | """准备原始数据:某网上商城从用户进入到下订单,中间各个操作过程中平均剩余用户的人数
6 |
7 | 漏斗图不需要x轴和y轴,但需要二维的列表,分别是某一个环节的名字,以及当前这个环节中的相对变化率数值
8 | [[环节名(变化率), 环节直接人数], [环节名(变化率), 环节直接人数], ...]
9 |
10 | * 环节名这里稍微加点东西:环节名里面要体现出各个环节相比上一环节的人数变化率
11 |
12 | 所以显然,下面的原始数据是需要组装的
13 | """
14 | # 存储标签的列表label
15 | label = ["展现", "点击", "访问", "咨询", "订单"]
16 | # 对应存储数量的列表num(非最终数值)
17 | num = [1000, 880, 264, 52.8, 5.28]
18 |
19 | """显示的最终数值生成
20 |
21 | 1、数据项:各环节占上一个环节的相对人数变化率(百分数值,不要百分号)
22 | 最开始的环节当然是100%
23 | 这里保留一位小数
24 | 2、标签项:假如按照 标签名+变化率 这种方式进行组合
25 | 3、组装数据各项和标签各项成为二维列表
26 | """
27 | # 计算各个环节人数相对变化率
28 | pass_rate = [100]
29 | # 从第2个元素开始,所以下标始于1
30 | for index in range(1, len(num)):
31 | relative_percentage = (num[index] / num[index - 1]) * 100
32 | # 保留一位小数
33 | relative_percentage = round(relative_percentage, 1)
34 | pass_rate.append(relative_percentage)
35 |
36 | # 标签项的组装,这种写法想象一下数据库的SQL语言,结合类比一下?
37 | label_rate = [f"{label_item}{rate_item}%"
38 | for label_index, label_item in enumerate(label)
39 | for rate_index, rate_item in enumerate(pass_rate)
40 | if label_index == rate_index]
41 |
42 | # 组装二维列表作为显示数据
43 | data_pair = [[label_rate_item, num_item]
44 | for label_rate_index, label_rate_item in enumerate(label_rate)
45 | for num_index, num_item in enumerate(num)
46 | if label_rate_index == num_index]
47 | # print(data_pair)
48 |
49 | """绘制漏斗图
50 |
51 | 每个环节(每个漏斗条)中间距离设置为10
52 | 数据系名称(series_name)设置为“网店商品浏览阶段人数变化示意”
53 | 隐藏图例
54 | 保存图片
55 | """
56 | # 保存路径
57 | resultPath = "./result"
58 | if not os.path.exists(path=resultPath):
59 | os.mkdir(path=resultPath)
60 | # 保存文件名
61 | resultFileName = "sales_section_funnel.html"
62 | # 执行绘图
63 | funnel = (
64 | Funnel()
65 | .set_global_opts(legend_opts=opts.LegendOpts(is_show=False))
66 | .add(
67 | series_name="网店商品浏览阶段人数变化示意",
68 | data_pair=data_pair,
69 | gap=10
70 | )
71 | .render(path=os.path.join(resultPath, resultFileName))
72 | )
73 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_1/result/sales_section_funnel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_2/example7_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Funnel
3 | import pyecharts.options as opts
4 |
5 | """准备原始数据:某网上商城从用户进入到下订单,用户行为在各个购买阶段的剩余人数
6 |
7 | 漏斗图不需要x轴和y轴,但需要二维的列表,分别是某一个环节的名字,以及当前这个环节中的相对变化率数值
8 | [[环节名, 相比上一环节人数变化率], [环节名, 相比上一环节人数变化率], [环节名, 相比上一环节人数变化率], ...]
9 |
10 | 所以显然,下面的原始数据是需要组装的
11 | """
12 | # 存储标签的列表label
13 | user_behavior = ["浏览商品", "加入购物车", "生成订单", "支付订单", "完成交易"]
14 | # 对应存储数量的列表num(非最终数值)
15 | num = [100, 40, 30, 20, 17]
16 |
17 | """显示的最终数值生成
18 |
19 | 1、数据项:各环节占上一个环节的相对人数变化率(百分数值,不要百分号)
20 | 最开始的环节当然是100%
21 | 这里保留一位小数
22 | 2、标签项:假如按照 标签名+变化率 这种方式进行组合
23 | 3、组装数据各项和标签各项成为二维列表
24 | """
25 | # 计算各个环节人数相对变化率
26 | pass_rate = [100]
27 | # 从第2个元素开始,所以下标始于1
28 | for index in range(1, len(num)):
29 | relative_percentage = (num[index] / num[index - 1]) * 100
30 | # 保留一位小数
31 | relative_percentage = round(relative_percentage, 1)
32 | pass_rate.append(relative_percentage)
33 |
34 | # 标签项的组装,这种写法想象一下数据库的SQL语言,结合类比一下?
35 | label_rate = [f"{label_item}{rate_item}%"
36 | for label_index, label_item in enumerate(user_behavior)
37 | for rate_index, rate_item in enumerate(pass_rate)
38 | if label_index == rate_index]
39 |
40 | # 组装二维列表作为显示数据(第一维是上一个)
41 | data_pair = [[label_rate[label_rate_index], num[num_index]]
42 | for label_rate_index, _ in enumerate(label_rate)
43 | for num_index, _ in enumerate(num)
44 | if label_rate_index == num_index]
45 | print(data_pair)
46 |
47 | """绘制漏斗图
48 |
49 | 图的标题设置为“用户行为转化率”
50 | 每个环节(每个漏斗条)中间距离设置为10
51 | 数据系名称(series_name)这里不设置
52 | 隐藏图例
53 | 保存图片
54 | """
55 | # 保存路径
56 | resultPath = "./result"
57 | if not os.path.exists(path=resultPath):
58 | os.mkdir(path=resultPath)
59 | # 保存文件名
60 | resultFileName = "user_conversion_rate_funnel.html"
61 | # 执行绘图
62 | funnel = (
63 | Funnel()
64 | .set_global_opts(
65 | title_opts=opts.TitleOpts(title="用户行为转化率"),
66 | legend_opts=opts.LegendOpts(is_show=False)
67 | )
68 | .add(
69 | series_name="",
70 | data_pair=data_pair,
71 | gap=10
72 | )
73 | .render(path=os.path.join(resultPath, resultFileName))
74 | )
75 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_2/result/user_conversion_rate_funnel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
133 |
134 |
135 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_3/example7_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Funnel
6 | import pyecharts.options as opts
7 |
8 | # 资源文件路径
9 | resourcesPath = "./resources"
10 | salesBookName = "销售漏斗.xlsx"
11 |
12 |
13 | def read_rows(wb: Workbook=None, sheetname=None) -> list:
14 | """
15 | 从excel文档中读出所有行,每一行都是列表,所有行存入一个大列表,返回出去
16 | 读取时,不做清洗,只是忠诚地把文件里的数据转移出来到列表里
17 | :param wb: excel工作簿(已经打开)
18 | :param sheetname: 工作表Worksheet名
19 | :return: list
20 | """
21 | # 选表
22 | sheet = wb[sheetname] # type: Worksheet
23 | # 读出所有行数据
24 | row_data = [list(rowContent) for rowContent in sheet.iter_rows(values_only=True)]
25 | return row_data
26 |
27 |
28 | # 加载工作簿
29 | salesBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, salesBookName)) # type: Workbook
30 | # 内有多个sheets,逐个遍历
31 | for teamSheetName in salesBook.sheetnames:
32 | # 选工作表
33 | teamSheet = salesBook[teamSheetName] # type: Worksheet
34 |
35 | # 取出表中数据
36 | rowData = read_rows(wb=salesBook, sheetname=teamSheetName)
37 | # 谈判阶段
38 | stages = rowData[0][1:]
39 | # 每个阶段达成的数量
40 | num = rowData[1][1:]
41 |
42 | # 处理数据,[标签项,数值项]处理成形如["目标客户100%", 1000]格式
43 | # 相对变化率的数值,计算时保留一位小数
44 | # 计算各个环节人数相对变化率
45 | pass_rate = [100]
46 | # 从第2个元素开始,所以下标始于1
47 | for index in range(1, len(num)):
48 | relative_percentage = (num[index] / num[index - 1]) * 100
49 | # 保留一位小数
50 | relative_percentage = round(relative_percentage, 1)
51 | pass_rate.append(relative_percentage)
52 |
53 | # 按照格式组装标签项
54 | label_item = []
55 | for common_index, rate_item in enumerate(pass_rate):
56 | label_item.append(f"{stages[common_index]}{rate_item}%")
57 | # 组装绘图用的数据对组装
58 | data_pair = []
59 | for common_index, num_item in enumerate(num):
60 | data_pair.append(
61 | [label_item[common_index], num_item]
62 | )
63 |
64 | # 绘制漏斗图,要求:
65 | # 1、隐藏图例;
66 | # 2、将标题设置为:f"{小组名称}销售漏斗"格式
67 | # 3、将三个图表分别保存到result目录下,命名格式:"{小组名称}.html"
68 | # 4、漏斗项之间的间距为10
69 | resultPath = "./result"
70 | if not os.path.exists(resultPath):
71 | os.mkdir(path=resultPath)
72 | resultFileName = f"{teamSheetName}_sales_funnel.html"
73 | funnel = (
74 | Funnel()
75 | .set_global_opts(
76 | title_opts=opts.TitleOpts(title=f"{teamSheetName}销售漏斗"),
77 | legend_opts=opts.LegendOpts(is_show=False)
78 | )
79 | .add(
80 | series_name="",
81 | data_pair=data_pair,
82 | gap=10
83 | )
84 | .render(path=os.path.join(resultPath, resultFileName))
85 | )
86 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_3/resources/销售漏斗.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/07转化跟踪之漏斗图/example7_3/resources/销售漏斗.xlsx
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_3/result/teamA_sales_funnel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_3/result/teamB_sales_funnel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_3/result/teamC_sales_funnel.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_4/example7_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Funnel, Tab
6 | import pyecharts.options as opts
7 |
8 | # 资源目录
9 | resourcesPath = "./resources"
10 | # 资源文件
11 | salesBookName = "销售.xlsx"
12 |
13 | # 打开excel文件表
14 | salesBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, salesBookName)) # type: Workbook
15 |
16 |
17 | def read_data_pair(sheet: Worksheet) -> list:
18 | """
19 | 从一个工作表中,读出生成一个漏斗图所需的必备数据对。
20 | :param sheet:正在处理的工作表
21 | :return:二元列表[标签项,数据项]为[f"{环节}{相对变化率}%", 对应数量]的元素所构成的二维列表。相对变化率保留1位小数
22 | """
23 | # 忠诚读取各行数据
24 | row_data = [list(rowContent) for rowContent in sheet.iter_rows(values_only=True)]
25 | # 原始数据:环节
26 | stages = row_data[0][1:]
27 | # 原始数据:各阶段达成数量
28 | num = [eval(str(data_item)) for data_item in row_data[1][1:]]
29 |
30 | # 计算各个环节人数相对变化率
31 | pass_rate = [100]
32 | # 从第2个元素开始,所以下标始于1
33 | for index in range(1, len(num)):
34 | relative_percentage = (num[index] / num[index - 1]) * 100
35 | # 保留一位小数
36 | relative_percentage = round(relative_percentage, 1)
37 | pass_rate.append(relative_percentage)
38 |
39 | # 按照格式组装标签项
40 | label_item = []
41 | for common_index, rate_item in enumerate(pass_rate):
42 | label_item.append(f"{stages[common_index]}{rate_item}%")
43 | # 组装绘图用的数据对组装
44 | data_pair = []
45 | for common_index, num_item in enumerate(num):
46 | data_pair.append(
47 | [label_item[common_index], num_item]
48 | )
49 |
50 | return data_pair
51 |
52 |
53 | # 用于添加所有绘制出来的漏斗图
54 | tab = Tab()
55 |
56 | for monthSheetName in salesBook.sheetnames:
57 | # 获取该表下用于绘图的数据对
58 | data_pair = read_data_pair(salesBook[monthSheetName])
59 | # 绘制漏斗图,要求:
60 | # 1、隐藏图例;
61 | # 2、每张图标题设置为:f"{月份}销售"
62 | # 3、图中每个漏斗项中间的距离为10
63 | # 4、多漏斗图用看板展示;
64 | # 5、保存
65 | funnel = (
66 | Funnel()
67 | .set_global_opts(
68 | title_opts=opts.TitleOpts(title=f"{monthSheetName}销售"),
69 | legend_opts=opts.LegendOpts(is_show=False)
70 | )
71 | .add(
72 | series_name="",
73 | data_pair=data_pair,
74 | gap=10
75 | )
76 | )
77 | tab.add(chart=funnel, tab_name=f"{monthSheetName}")
78 |
79 | # 保存看板图
80 | resultPath = "./result"
81 | if not os.path.exists(resultPath):
82 | os.mkdir(path=resultPath)
83 | resultFileName = "year_funnel_tab.html"
84 |
85 | tab.render(path=os.path.join(resultPath, resultFileName))
86 |
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/example7_4/resources/销售.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/07转化跟踪之漏斗图/example7_4/resources/销售.xlsx
--------------------------------------------------------------------------------
/07转化跟踪之漏斗图/whatisFunnelChart.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/07转化跟踪之漏斗图/whatisFunnelChart.md
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_1/example8_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from openpyxl import Workbook
3 | from openpyxl.worksheet.worksheet import Worksheet
4 | from pyecharts.charts import Bar, Timeline
5 | import pyecharts.options as opts
6 | import openpyxl
7 |
8 | # 工作簿统一所在路径
9 | resourcesPath = "./resources"
10 | # 工作簿名
11 | gdpBookName = "历年前十大经济体.xlsx"
12 | # 工作表名
13 | gdpSheetName = "GDP"
14 | gdpSheet = openpyxl.load_workbook(filename=os.path.join(resourcesPath, gdpBookName))[gdpSheetName] # type: Worksheet
15 |
16 |
17 | def get_data(row_num):
18 | """
19 | 传入行数,返回用于绘制柱状图所必备的数据信息,将已经打开的工作表作为全局信息
20 | :param row_num:工作表的行数
21 | :return:三元组(年份,国家名列表,对应的GDP数值(单位:亿元))
22 | """
23 |
24 | # 忠诚地读出当前行和下一行的原始数据,形如:
25 | # [(1970, '美国', '苏联', '日本', '西德', '法国', '英国', '意大利', '中国', '加拿大', '印度'),
26 | # (None, 1024.9, 433.412, 209.071, 208.869, 146.985, 124.883, 109.258, 91.506, 86.304, 61.332)]
27 | org_data = [data_item for data_item in gdpSheet.iter_rows(min_row=row_num, max_row=row_num+1, values_only=True)]
28 |
29 | # 提取年份
30 | year_ = org_data[0][0]
31 | # 提取国家列表
32 | country_list = org_data[0][1:]
33 | # 提取对应的GDP取值
34 | gdp_list = org_data[1][1:]
35 |
36 | return year_, country_list, gdp_list
37 |
38 |
39 | # 绘制轮播柱状图
40 | timeline = Timeline()
41 |
42 | # 扫描偶数行号,因为每一个偶数行号对应着一组新的数据,原表格一共有21行,暂时未找到合适的方法判断行数,所以直接用绝对数值
43 | for rowNum in range(2, 21, 2):
44 | # 获取当前行绘图所需的(年份,x轴,y轴)所需数据
45 | year, x_data, y_data = get_data(row_num=rowNum)
46 |
47 | # 绘制单个柱状图
48 | # 1. 图例隐藏
49 | # 2. 图表的标题设置为:"xxxx年前十大经济体GDP排名";
50 | # 3. 逐个添加柱状图到轮播图,轮播图的每个时间节点设置:xxxx年;
51 | # 4. 将图表保存
52 | timeline.add(
53 | time_point=f"{year}年",
54 | chart=(
55 | Bar()
56 | .set_global_opts(
57 | title_opts=opts.TitleOpts(title=f"{year}年前十大经济体GDP排名"),
58 | legend_opts=opts.LegendOpts(is_show=False)
59 | )
60 | .add_xaxis(xaxis_data=x_data)
61 | .add_yaxis(
62 | series_name="",
63 | y_axis=y_data
64 | )
65 | )
66 | )
67 |
68 | # 保存轮播图路径
69 | resultPath = "./result"
70 | if not os.path.exists(resultPath):
71 | os.mkdir(path=resultPath)
72 | # 文件名
73 | resultFileName = "GDP_bar_timeline.html"
74 | # 执行保存
75 | timeline.render(path=os.path.join(resultPath, resultFileName))
76 |
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_1/resources/历年前十大经济体.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/08多维展示之轮播图/example8_1/resources/历年前十大经济体.xlsx
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_2/example8_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from openpyxl import Workbook
3 | from openpyxl.worksheet.worksheet import Worksheet
4 | from pyecharts.charts import Bar, Timeline
5 | import pyecharts.options as opts
6 | import openpyxl
7 |
8 | # 资源路径
9 | resourcesPath = "./resources"
10 | # 月产品线销量报表工作簿
11 | monthSalesBookName = "timeline.xlsx"
12 | # 打开工作簿
13 | monthSalesBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, monthSalesBookName)) # type: Workbook
14 |
15 |
16 | def read_sheet(sheet_name: str):
17 | """
18 | 传入工作表,返回当前工作表中需要用于绘图的数据。
19 |
20 | 前置条件:所需的工作簿已打开.
21 |
22 | :param sheet_name: 当前工作表的名称
23 |
24 | :return: 元组(表头-x轴, (商家名1, x轴对应的y轴数据组1), (商家名2, x轴对应的y轴数据组2), ...)
25 |
26 | """
27 |
28 | # 选中工作表
29 | month_sales_sheet = monthSalesBook[sheet_name] # type: Worksheet
30 | # 取出所有原始数据,先不做处理,形如:
31 | # [(None, '草莓', '芒果', '葡萄', '雪梨', '西瓜', '柠檬', '车厘子'),
32 | # ('商家A', 130, 136, 112, 61, 149, 99, 62),
33 | # ('商家B', 82, 112, 41, 50, 40, 91, 117)]
34 | org_data = [org for org in month_sales_sheet.iter_rows(values_only=True)]
35 |
36 | # 提取产品信息列表
37 | product_list = org_data[0][1:]
38 | # 提取商家及其销量信息
39 | sales_info = org_data[1:]
40 |
41 | # 组装
42 | plot_data = [product_list]
43 | for info in sales_info:
44 | plot_data.append(info)
45 |
46 | return tuple(plot_data)
47 |
48 |
49 | # 绘制轮播图,节点名设置为月份(工作表的名字)
50 | # 柱状图每个数据系名设置为商户的名字:商家X;
51 | # 每个月份图表的标题设置为"月份"+"销量":X月销量;
52 | # 将图表保存
53 | timeline = Timeline()
54 | # 扫描所有工作表,逐个绘制柱状图加进轮播图里面
55 | for sheetName in monthSalesBook.sheetnames:
56 | # 取出用于绘图的一组数据:(表头-x轴, (商家名1, x轴对应的y轴数据组1), (商家名2, x轴对应的y轴数据组2), ...)
57 | packedData = read_sheet(sheetName)
58 |
59 | # 提取x轴数据
60 | x_data = packedData[0]
61 |
62 | # 提取多组y轴数据字典
63 | y_data_dict = dict()
64 | for y_data_item in packedData[1:]:
65 | # 键值对——'商家名': [对应x轴的系列取值]
66 | y_data_dict[y_data_item[0]] = y_data_item[1:]
67 |
68 | # 绘柱状图
69 | bar = (
70 | Bar()
71 | .set_global_opts(title_opts=opts.TitleOpts(title=f"{sheetName}销量"))
72 | .add_xaxis(xaxis_data=x_data)
73 | )
74 | for k_vendor, v_y_data in y_data_dict.items():
75 | bar.add_yaxis(
76 | series_name=k_vendor,
77 | y_axis=v_y_data
78 | )
79 | # 加进轮播图
80 | timeline.add(chart=bar, time_point=sheetName)
81 |
82 | # 保存轮播图路径
83 | resultPath = "./result"
84 | if not os.path.exists(path=resultPath):
85 | os.mkdir(path=resultPath)
86 | # 文件名
87 | resultFileName = "monthly_sales_timeline.html"
88 | # 执行保存
89 | timeline.render(path=os.path.join(resultPath, resultFileName))
90 |
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_2/resources/timeline.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/08多维展示之轮播图/example8_2/resources/timeline.xlsx
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_3/example8_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Pie, Timeline
6 | import pyecharts.options as opts
7 |
8 | # 资源文件夹
9 | resourcesPath = "./resources"
10 | # 每月销售额工作簿
11 | monthlySalesBookName = "每月销售额.xlsx"
12 | # 工作表名
13 | monthlySalesSheetName = "各商品每月销售额"
14 | # 打开工作表
15 | monthlySalesSheet = openpyxl.load_workbook(
16 | filename=os.path.join(resourcesPath, monthlySalesBookName))[monthlySalesSheetName]
17 |
18 |
19 | def read_excel(sheet: Worksheet) -> list:
20 | """
21 | 忠诚地读取出工作表中的原始内容,不做任何处理。
22 |
23 | :param sheet: 正在读取的工作表
24 |
25 | :return: 由各行数据组成的列表,每行也是一个列表
26 | """
27 | org_data = [list(data_item) for data_item in sheet.iter_rows(values_only=True)]
28 | return org_data
29 |
30 |
31 | def get_data(org_data: list, row: int) -> tuple:
32 | """
33 | 利用read_excel读取出的数据,取出绘制一个饼图所需的数据。
34 |
35 | 屏蔽空数据或者0数据。
36 |
37 | :param row: 指定读取的excel表格中第几行的数据(从2开始,跳过第1行表头)
38 | :param org_data: excel表格里,由各行数据组成的列表,每行也是一个列表
39 |
40 | :return: 二元组:(月份,[(标签1, 数据1), (标签2, 数据2), ...])
41 | """
42 | # 取出用来做标签的数据
43 | labels = org_data[0][1:]
44 |
45 | # 取出相应行的数据
46 | row_data = [row_item for row_item in org_data[row]]
47 | # 月份和数据
48 | month_, data = row_data[0], row_data[1:]
49 |
50 | # 从标签、数据中组合出绘制饼状图所需的数据对
51 | sales_list = []
52 | for index in range(len(labels)):
53 | if data[index] == 0:
54 | continue
55 | data_pair_item = (labels[index], data[index])
56 | sales_list.append(data_pair_item)
57 |
58 | # 返回(月份, 绘图用的数据对列表)
59 | return month_, sales_list
60 |
61 |
62 | # 取出excel表格中的内容
63 | orgData = read_excel(monthlySalesSheet)
64 |
65 | # 根据12个月的数据,分别绘制出所需的图形
66 | # 1. 每组数据以环状南丁格尔玫瑰图展示
67 | # 2. 将玫瑰图的数据系名设置为空;
68 | # 3. 环内径为"20%", 最大外径为"60%";
69 | # 4. 数据项标签的格式为"{百分比}%"
70 | # 5. 标签内置于每块饼中;
71 | # 6. 玫瑰图类型设置为圆心角相同,仅通过半径展示数据项大小差别
72 | # 7. 将每个月份图表的标题设置为"月份"+"销售额组成":x月销售额组成;
73 | # 8. 轮播图各轮播节点设置为月份:x月;
74 | # 9. 将轮播玫瑰图保存
75 | timeline = Timeline()
76 | for rowNum in range(1, len(orgData)):
77 | # 得到当前行用于绘图的数据
78 | month, dataPair = get_data(org_data=orgData, row=rowNum)
79 | timeline.add(
80 | time_point=month,
81 | chart=(
82 | Pie()
83 | .set_global_opts(title_opts=opts.TitleOpts(title=f"{month}销售额组成"))
84 | .add(
85 | series_name="",
86 | data_pair=dataPair,
87 | radius=["20%", "60%"],
88 | rosetype="radius",
89 | label_opts=opts.LabelOpts(
90 | position="inside",
91 | formatter="{d}%"
92 | )
93 | )
94 | )
95 | )
96 |
97 | # 保存路径
98 | resultPath = "./result"
99 | if not os.path.exists(path=resultPath):
100 | os.mkdir(path=resultPath)
101 | # 文件名
102 | resultFileName = "sales_rose_pie_timeline.html"
103 | # 执行保存
104 | timeline.render(path=os.path.join(resultPath, resultFileName))
105 |
--------------------------------------------------------------------------------
/08多维展示之轮播图/example8_3/resources/每月销售额.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/08多维展示之轮播图/example8_3/resources/每月销售额.xlsx
--------------------------------------------------------------------------------
/08多维展示之轮播图/whatisTimeline.md:
--------------------------------------------------------------------------------
1 | # 轮播图(Timeline)
2 |
3 | 轮播图可以给原来的图表增加一个维度,可以沿着时间线或者某种逻辑滚动播放,展现出时间或逻辑的变化,展现更多信息。
4 |
5 | 轮播图其实不难画:
6 |
7 | * 按照之前的板块介绍,绘制出任何需要的图表
8 |
9 | * 创建一个Timeline,把之前画的图表按照需要逐个添加到Timeline里面去,就生成了
10 |
--------------------------------------------------------------------------------
/09位置之地图/example9_1/example9_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Map
3 | import pyecharts.options as opts
4 |
5 | # 准备原始数据(从文件中读取数据的过程省略):各国排名世界top500财富榜的企业个数
6 | # 在地图上做可视化的绘图数据格式:[("地点1", 对应数值1), ("地点2", 对应数值2), ...]
7 | # 国家和对应的数据,组成了列表dataList
8 | dataList = [('China', 124), ('United States', 121), ('Japan', 53), ('France', 31), ('Germany', 27),
9 | ('United Kingdom', 22), ('Korea', 14), ('Switzerland', 14), ('Canada', 13), ('Netherlands', 13)]
10 |
11 |
12 | # 地图绘制需求
13 | # 1. 数据系列名为空
14 | # 2. 参数图片类型设置为世界地图(参数怎么指定,需要查阅文档)
15 | # 3. 数据标签隐藏
16 | # 4. 视觉映射配置项,将最大映射值设为130
17 | # 5. 设置标题为"排名前10的国家"
18 | # 6. 保存
19 | # 存储路径
20 | resultPath = "./result"
21 | if not os.path.exists(path=resultPath):
22 | os.mkdir(path=resultPath)
23 | # 存储文件名
24 | resultFileName = "top10property_world_map.html"
25 | # 执行绘图
26 | mapChart = (
27 | Map()
28 | .set_global_opts(
29 | title_opts=opts.TitleOpts("排名前10的国家"),
30 | visualmap_opts=opts.VisualMapOpts(max_=130)
31 | )
32 | .add(
33 | series_name="",
34 | data_pair=dataList,
35 | label_opts=opts.LabelOpts(is_show=False),
36 | maptype="world"
37 | )
38 | .render(path=os.path.join(resultPath, resultFileName))
39 | )
40 |
--------------------------------------------------------------------------------
/09位置之地图/example9_1/result/top10property_world_map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
12 |
174 |
175 |
176 |
--------------------------------------------------------------------------------
/09位置之地图/example9_2/example9_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Map
6 | import pyecharts.options as opts
7 |
8 | # 资源文件统一所在目录
9 | resourcesPath = "./resources"
10 | # 降雨量数据工作簿名
11 | rainFallBookName = "全国降雨量.xlsx"
12 | # 2017年数据工作表名
13 | rainFallSheetName = "2017年降水量"
14 | # 打开文件选表
15 | rainFallSheet = openpyxl.load_workbook(
16 | filename=os.path.join(resourcesPath, rainFallBookName)
17 | )[rainFallSheetName] # type: Worksheet
18 |
19 | # 获取原始数据:2017年全国各省降水量(毫米),跳过表头
20 | orgData = [row_item for row_item in rainFallSheet.iter_rows(min_row=2, values_only=True)]
21 |
22 | # 清洗数据,去掉空数据。组装绘图用的数据对
23 | dataPair = [data_item for data_item in orgData
24 | if None not in data_item]
25 |
26 | # 绘制地图需求
27 | # 1. 标记(symbol)隐藏、标签隐藏
28 | # 2. 添加视觉映射,最大值映射值设为230
29 | # 3. 组件过渡颜色设置为["#E0ECF8", "#045FB4"],冷色系的那种,让人感觉是下雨的感觉
30 | # 4. 标题设为"2017年全国降雨量"
31 | # 5. 保存
32 | # 保存路径
33 | resultPath = "./result"
34 | if not os.path.exists(path=resultPath):
35 | os.mkdir(path=resultPath)
36 | # 保存文件名
37 | resultFileName = "rainfall_china_map.html"
38 | # 执行绘图
39 | mapChart = (
40 | Map()
41 | .set_global_opts(
42 | title_opts=opts.TitleOpts(title="2017年全国降雨量", subtitle="单位:mm"),
43 | visualmap_opts=opts.VisualMapOpts(
44 | max_=230,
45 | range_color=["#E0ECF8", "#045FB4"]
46 | ),
47 | legend_opts=opts.LegendOpts(is_show=False)
48 | )
49 | .add(
50 | series_name="降水量(单位:mm)",
51 | data_pair=dataPair,
52 | label_opts=opts.LabelOpts(is_show=False),
53 | is_map_symbol_show=False
54 | )
55 | .render(path=os.path.join(resultPath, resultFileName))
56 | )
57 |
--------------------------------------------------------------------------------
/09位置之地图/example9_2/resources/全国降雨量.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/09位置之地图/example9_2/resources/全国降雨量.xlsx
--------------------------------------------------------------------------------
/09位置之地图/example9_3/example9_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Map, Timeline
6 | import pyecharts.options as opts
7 |
8 | # 资源文件统一所在目录
9 | resourcesPath = "./resources"
10 | # 降雨量数据工作簿名
11 | gpdBookName = "2010-2017年各省份历年GDP.xlsx"
12 | # 打开文件
13 | gpdBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, gpdBookName)) # type: Workbook
14 |
15 |
16 | def get_data(year: str) -> tuple:
17 | """
18 | 指定工作表名year,返回绘图所需的数据
19 |
20 | :param year: 年份,是字符串
21 |
22 | :return: 绘图所需数据,格式(年份——数值类型的年份, [(省份1, GDP取值1), (省份2, GDP取值2), ...])
23 | """
24 | # 选中工作表
25 | year_sheet = gpdBook[year] # type: Worksheet
26 |
27 | # 取出全国当前的各省GDP数据
28 | gdp_list = [row_item for row_item in year_sheet.iter_rows(min_row=2, values_only=True)]
29 | # 清洗数据,去掉含空项
30 | gdp_list = [item for item in gdp_list if None not in item]
31 |
32 | return (
33 | eval(str(year)),
34 | gdp_list
35 | )
36 |
37 |
38 | # 扫描各个工作表,绘制轮播图
39 | timeline = Timeline()
40 | for yearSheetName in gpdBook.sheetnames:
41 | # 取出绘图所需的数据
42 | year, dataPair = get_data(year=yearSheetName)
43 |
44 | # 绘制单组地图需求:
45 | # 1. 地图类型设置为中国地图;
46 | # 2. 视觉映射配置项最大映射值设置为3000;
47 | # 3. 标题设置为f"{data[0]}年各省GDP(单位:10亿人民币)";
48 | # 4. 轮播图时间节点设置为“xxxx年”
49 | # 5. 隐藏图例
50 | timeline.add(
51 | time_point=f"{year}年",
52 | chart=(
53 | Map()
54 | .set_global_opts(
55 | title_opts=opts.TitleOpts(title=f"{year}年各省GDP(单位:10亿人民币)"),
56 | visualmap_opts=opts.VisualMapOpts(max_=3000)
57 | )
58 | .add(
59 | series_name=f"{year}年",
60 | maptype="china",
61 | data_pair=dataPair
62 | )
63 | )
64 | )
65 |
66 | # 保存路径
67 | resultPath = "./result"
68 | if not os.path.exists(path=resultPath):
69 | os.mkdir(path=resultPath)
70 | # 保存文件名
71 | resultFileName = "gdp_map_timeline.html"
72 | # 执行保存
73 | timeline.render(path=os.path.join(resultPath, resultFileName))
74 |
--------------------------------------------------------------------------------
/09位置之地图/example9_3/resources/2010-2017年各省份历年GDP.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/09位置之地图/example9_3/resources/2010-2017年各省份历年GDP.xlsx
--------------------------------------------------------------------------------
/10局部密度之热力图/example10_1/example10_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import HeatMap
6 | import pyecharts.options as opts
7 |
8 | # 资源文件所在目录
9 | resourcesPath = "./resources"
10 | # 便利店文件名
11 | storeBookName = "便利店.xlsx"
12 | # 一周订单量工作表名
13 | orderSheetName = "一周订单量"
14 | # 打开工作表
15 | orderSheet = openpyxl.load_workbook(
16 | filename=os.path.join(resourcesPath, storeBookName)
17 | )[orderSheetName] # type: Worksheet
18 | # 取出各行的所有原始数据
19 | org_data = [list(row_item) for row_item in orderSheet.iter_rows(values_only=True)]
20 | # print(org_data)
21 |
22 |
23 | # 提取数据
24 | # 作为x轴坐标的几点钟数据
25 | timeList = [time_order_num[0] for time_order_num in org_data[1:]]
26 | # 作为y轴坐标的星期几数据
27 | weekList = org_data[0][1:]
28 | # 提取热力图中的色块取值信息
29 | heatMapList = []
30 | for row_index, row_item in enumerate(org_data[1:]):
31 | for col_index, sales_value in enumerate(row_item[1:]):
32 | heatMapList.append(
33 | [row_index, col_index, sales_value]
34 | )
35 | # print(heatMapList)
36 |
37 |
38 | # 绘制所需的热力图要求
39 | #
40 | # 1. x轴是几点钟的时间;
41 | # 2. 图例隐藏
42 | # 3. y轴是星期几的时间
43 | # 4. 色块每一个地方的坐标及取值用上;
44 | # 5. 视觉映射配置项,将最大值映射值设置为70;
45 | # 6. x轴标签90度旋转防止遮挡;
46 | # 7. 标题设置为:一周订单量;
47 | # 8. 执行保存
48 | # 保存路径
49 | resultPath = "./result"
50 | if not os.path.exists(path=resultPath):
51 | os.mkdir(path=resultPath)
52 | # 存储文件名称
53 | resultFileName = "week_order_heatmap.html"
54 |
55 | heatMap = (
56 | HeatMap()
57 | .set_global_opts(
58 | title_opts=opts.TitleOpts(title="一周订单量"),
59 | visualmap_opts=opts.VisualMapOpts(max_=70),
60 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=90))
61 | )
62 | .add_xaxis(xaxis_data=timeList)
63 | .add_yaxis(
64 | yaxis_data=weekList,
65 | value=heatMapList,
66 | series_name="一周订单量"
67 | )
68 | .render(path=os.path.join(resultPath, resultFileName))
69 | )
70 |
71 |
72 |
--------------------------------------------------------------------------------
/10局部密度之热力图/example10_1/resources/便利店.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/10局部密度之热力图/example10_1/resources/便利店.xlsx
--------------------------------------------------------------------------------
/10局部密度之热力图/example10_2/example10_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import HeatMap
6 | import pyecharts.options as opts
7 |
8 | # 资源文件路径
9 | resourcesPath = "./resources"
10 |
11 | # 票价表文件名
12 | ticketBookName = "票价表.xlsx"
13 | # 一号线工作表
14 | lineOneSheetName = "一号线"
15 |
16 | # 读文件,选表
17 | lineOneSheet = openpyxl.load_workbook(
18 | filename=os.path.join(resourcesPath, ticketBookName)
19 | )[lineOneSheetName] # type: Worksheet
20 |
21 | # 取出表中所有数据
22 | org_data = [row_item for row_item in lineOneSheet.iter_rows(min_row=1, values_only=True)]
23 | print(org_data)
24 |
25 | # x轴上的标签和y轴的标签都是站台名称
26 | # 提取x轴和y轴的标签
27 | xData = org_data[0][1:]
28 | yData = [row_item[0] for row_item in org_data[1:]]
29 | # 扫描行列,组合出热力图取值二维列表(非常注意一点:表的列是数据的x轴,表的行是数据的y轴)
30 | value_list = []
31 | for x_index, sheetRow in enumerate(org_data[1:]):
32 | for y_index, value_ in enumerate(sheetRow[1:]):
33 | value_list.append(
34 | [x_index, y_index, value_]
35 | )
36 | print(value_list)
37 |
38 | # 绘制热力图需求:
39 | # 1. 画布的宽为"1000px",高为"800px";
40 | # 2. 隐藏图例;
41 | # 3. 数据标签显示在内部居中;
42 | # 4. 视觉配置项,最大值映射值设置为10;
43 | # 5. x轴上的标签旋转90度防止遮挡;
44 | # 6. 标题设置为"一号线票价表";
45 | # 7. 保存
46 | # 保存路径
47 | resultPath = "./result"
48 | if not os.path.exists(path=resultPath):
49 | os.mkdir(path=resultPath)
50 | # 保存文件名
51 | resultFileName = "ticket_price_heatmap.html"
52 | # 执行绘图
53 | heatMap = (
54 | HeatMap(
55 | init_opts=opts.InitOpts(width="1000px", height="800px")
56 | )
57 | .set_global_opts(
58 | title_opts=opts.TitleOpts(title="一号线票价表", subtitle="单位(元)"),
59 | legend_opts=opts.LegendOpts(is_show=False),
60 | visualmap_opts=opts.VisualMapOpts(max_=10),
61 | xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=90))
62 | )
63 | .add_xaxis(xaxis_data=xData)
64 | .add_yaxis(
65 | series_name="",
66 | yaxis_data=yData,
67 | value=value_list,
68 | label_opts=opts.LabelOpts(position="inside")
69 | )
70 | .render(path=os.path.join(resultPath, resultFileName))
71 | )
72 |
--------------------------------------------------------------------------------
/10局部密度之热力图/example10_2/resources/票价表.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/10局部密度之热力图/example10_2/resources/票价表.xlsx
--------------------------------------------------------------------------------
/11单页多图之页面组合图/example11_1/example11_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts import options as opts
3 | from pyecharts.charts import Bar, Page
4 |
5 |
6 | def mi() -> Bar:
7 | """
8 | 绘制小米手机的点赞、转发、评论数据的柱状图,绘图需求:
9 |
10 | 1.设置图表主题为macarons
11 |
12 | 2.设置x轴,为点赞数、转发数、评论数;
13 |
14 | 3.设置y轴,传入数据,这里为了方便演示页面组合图,openpyxl读取数据环节先跳过,
15 | 所需数据已直接给出:
16 |
17 | * 数据系列为mi10_young的三项数据为[405020, 159455, 160529]
18 |
19 | * 数据系列为mi10_pro的三项数据为[131234, 11431, 36922]
20 |
21 | * 数据系列为redmi_k30_pro的三项数据为[110892, 7518, 29415]
22 |
23 | 4.标题为“2020小米新品手机微博数据”,副标题为“各型号获赞、评论、转发数”;
24 |
25 | 5.图例右端位置在相对画布作图区右25%处位置。
26 |
27 | 6.y轴取值的最大值要和另一张图统一(取值500000),
28 | 确保和另一张柱状图直观比对时不出现可视化陷阱错误
29 |
30 | :return: 绘制完成的小米数据柱状图
31 | """
32 | return (
33 | Bar(init_opts=opts.InitOpts(theme="macarons"))
34 | .set_global_opts(
35 | title_opts=opts.TitleOpts(title="2020小米新品手机微博数据", subtitle="各型号获赞、评论、转发数"),
36 | legend_opts=opts.LegendOpts(pos_right="25%"),
37 | yaxis_opts=opts.AxisOpts(max_=500000)
38 | )
39 | .add_xaxis(xaxis_data=["点赞数", "转发数", "评论数"])
40 | .add_yaxis(series_name="mi10_young", y_axis=[405020, 159455, 160529])
41 | .add_yaxis(series_name="mi10_pro", y_axis=[131234, 11431, 36922])
42 | .add_yaxis(series_name="redmi_k30_pro", y_axis=[110892, 7518, 29415])
43 | )
44 |
45 |
46 | def huawei() -> Bar:
47 | """
48 | 绘制华为手机的点赞、转发、评论数据的柱状图,绘图需求:
49 |
50 | 1.设置图表主题为macarons
51 |
52 | 2.设置x轴,为点赞数、转发数、评论数;
53 |
54 | 3.设置y轴,传入数据,这里为了方便演示页面组合图,openpyxl读取数据环节先跳过,
55 | 所需数据已直接给出:
56 |
57 | * 数据系列为honor_x10的三项数据为[315750, 123680, 143533]
58 |
59 | * 数据系列为honor_30s的三项数据为[101736, 9841, 28089]
60 |
61 | * 数据系列为huawei_nova7的三项数据为[156793, 12412, 35721]
62 |
63 | 4.标题为“同价位华为为手机微博数据”,副标题为“各型号获赞、评论、转发数”;
64 |
65 | 5.图例右端位置在相对画布作图区右25%处位置。
66 |
67 | 6.y轴取值的最大值要和另一张图统一(取值500000),
68 | 确保和另一张柱状图直观比对时不出现可视化陷阱错误
69 |
70 | :return: 绘制完成的华为数据柱状图
71 | """
72 | return (
73 | Bar(init_opts=opts.InitOpts(theme="macarons"))
74 | .set_global_opts(
75 | title_opts=opts.TitleOpts(title="同价位华为为手机微博数据", subtitle="各型号获赞、评论、转发数"),
76 | legend_opts=opts.LegendOpts(pos_right="25%"),
77 | yaxis_opts=opts.AxisOpts(max_=500000)
78 | )
79 | .add_xaxis(xaxis_data=["点赞数", "转发数", "评论数"])
80 | .add_yaxis(series_name="honor_x10", y_axis=[315750, 123680, 143533])
81 | .add_yaxis(series_name="honor_30s", y_axis=[101736, 9841, 28089])
82 | .add_yaxis(series_name="huawei_nova7", y_axis=[156793, 12412, 35721])
83 | )
84 |
85 |
86 | # 绘制页面组合图需求:布局形式为简单布局,就这一个,没了,此外就记得保存
87 | # 保存路径
88 | resultPath = "./result"
89 | if not os.path.exists(path=resultPath):
90 | os.mkdir(path=resultPath)
91 | # 保存文件名
92 | resultFilePath = "weiboPhoneCompete_bar_page.html"
93 | page = (
94 | Page(layout=Page.SimplePageLayout)
95 | .add(
96 | mi(),
97 | huawei()
98 | )
99 | .render(path=os.path.join(resultPath, resultFilePath))
100 | )
101 |
--------------------------------------------------------------------------------
/11单页多图之页面组合图/example11_2/example11_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Pie, Funnel, Page
3 | from pyecharts import options as opts
4 |
5 |
6 | def rose():
7 | """
8 | 通过玫瑰图展示每个季度的销量占比,绘图需求:
9 |
10 | 1.主题为dark,标题为“销售占比”
11 |
12 | 2.隐藏图例
13 |
14 | 3.玫瑰图圆心角半径相同,仅通过半径区分数据大小
15 |
16 | 4.绘图所用数据对已给出,这里省略从文件读入数据的过程:
17 | [("数据线", 3884), ("手机膜", 7298), ("手机壳", 5763),("指环支架", 1326),("充电宝", 1889)]
18 |
19 | :return: 绘制好的玫瑰图
20 | """
21 | return (
22 | Pie(init_opts=opts.InitOpts(theme="dark"))
23 | .set_global_opts(
24 | title_opts=opts.TitleOpts("销售占比"),
25 | legend_opts=opts.LegendOpts(is_show=False)
26 | )
27 | .add(
28 | series_name="",
29 | data_pair=[("数据线", 3884), ("手机膜", 7298), ("手机壳", 5763),("指环支架", 1326),("充电宝", 1889)],
30 | rosetype="area"
31 | )
32 | )
33 |
34 |
35 | def lou():
36 | """
37 | 通过漏斗图展示店铺订单的转化效率,绘制需求:
38 |
39 | 1.主题为dark
40 |
41 | 2.标题为“订单转化效率”,隐藏图例
42 |
43 | 3.绘图所用数据对已给出,这里省略从文件读入数据的过程:
44 | [("访问", 100), ("搜索", 78.12), ("点击", 35.74), ("加购", 17.17), ("订单", 2.62)]
45 |
46 | :return: 绘制好的漏斗图
47 | """
48 | # 使用Funnel()函数创建实例赋值给funnel
49 | # 使用InitOpts(),传入参数theme="dark",赋值给init_opts
50 | return (
51 | Funnel(init_opts=opts.InitOpts(theme="dark"))
52 | .set_global_opts(
53 | legend_opts=opts.LegendOpts(is_show=False),
54 | title_opts=opts.TitleOpts(title="订单转化效率")
55 | )
56 | .add(
57 | series_name="",
58 | data_pair=[("访问", 100), ("搜索", 78.12), ("点击", 35.74), ("加购", 17.17), ("订单", 2.62)],
59 | )
60 | )
61 |
62 |
63 | # 绘制页面组合图,绘制需求:简单布局
64 | # 保存路径
65 | resultPath = "./result"
66 | if not os.path.exists(path=resultPath):
67 | os.mkdir(path=resultPath)
68 | # 保存文件名
69 | resultFileName = "sales_rose_funnel_page.html"
70 | page = (
71 | Page(layout=Page.SimplePageLayout)
72 | .add(
73 | rose(),
74 | lou()
75 | )
76 | .render(path=os.path.join(resultPath, resultFileName))
77 | )
78 |
--------------------------------------------------------------------------------
/11单页多图之页面组合图/example11_3/resources/hiking1.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/11单页多图之页面组合图/example11_3/resources/hiking1.xlsx
--------------------------------------------------------------------------------
/12数据分布之箱线图/example12_1/example12_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Boxplot, Grid
3 | import pyecharts.options as opts
4 |
5 | # 准备原始数据(为方便直观表达绘制过程,这里读表的过程先跳过)
6 | # x轴数据
7 | xData = ["15℃", "20℃", "25℃", "30℃", "35℃"]
8 | # 用于绘制y轴的原始数据(假设一组yi对应一个x_data下的实验组测得的一组数据)
9 | y1 = [383, 312, 348, 388, 375, 389, 432, 373, 377, 384]
10 | y2 = [412, 432, 421, 354, 378, 392, 407, 413, 415, 405]
11 | y3 = [400, 388, 397, 352, 423, 447, 378, 377, 395, 387]
12 | y4 = [278, 288, 254, 213, 256, 278, 267, 256, 278, 266]
13 | y5 = [213, 215, 234, 232, 278, 188, 223, 234, 225, 231]
14 |
15 | # 绘制箱线图
16 | boxplot = Boxplot()
17 | # 生成绘箱线图图用的y轴数据(即每一组yi)的[下限值,下四分位点,中位数,上四分位点,上限值]
18 | yData = boxplot.prepare_data([y1, y2, y3, y4, y5])
19 | # print(y_data)
20 | # 得到绘制5组温度下对应箱线图的[下限值,下四分位点,中位数,上四分位点,上限值]数据
21 | # [[312, 366.75, 380.0, 388.25, 432], [354, 388.5, 409.5, 416.5, 432], [352, 377.75, 391.5, 405.75, 447],
22 | # [213, 255.5, 266.5, 278.0, 288], [188, 214.5, 228.0, 234.0, 278]]
23 |
24 | # 执行绘图
25 | # 添加x轴数据
26 | boxplot.add_xaxis(xaxis_data=xData)
27 | # 添加y轴数据
28 | boxplot.add_yaxis(series_name="实验组数据", y_axis=yData)
29 |
30 | # 保存路径
31 | resultPath = "./result"
32 | if not os.path.exists(path=resultPath):
33 | os.mkdir(path=resultPath)
34 | # 保存文件名
35 | resultFilePath = "experiment_gp_boxplot.html"
36 | # 设置标题和副标题
37 | boxplot.set_global_opts(
38 | title_opts=opts.TitleOpts(title="探究温度对化肥有效成分含量的影响", subtitle="每种温度下共采集10组数据"),
39 | xaxis_opts=opts.AxisOpts(name="温度"),
40 | yaxis_opts=opts.AxisOpts(name="有效含量值(单位: g/500g)")
41 | )
42 |
43 | # 调整图形位置,解决副标题和y轴重叠问题
44 | grid = (
45 | Grid(init_opts=opts.InitOpts(height="600px"))
46 | .add(
47 | chart=boxplot,
48 | grid_opts=opts.GridOpts(pos_top="20%")
49 | )
50 | )
51 |
52 | # 执行保存
53 | grid.render(path=os.path.join(resultPath, resultFilePath))
54 |
--------------------------------------------------------------------------------
/12数据分布之箱线图/example12_2/example12_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Boxplot
3 | import pyecharts.options as opts
4 |
5 | # 准备原始数据
6 | # x轴:各学科名称
7 | xData = ["物理", "化学", "生物", "历史", "政治", "地理"]
8 | # 以及xi轴对应yi,yi是该科目多次调考的考试成绩
9 | y1 = [83, 88, 93, 79, 86, 89, 95, 90, 94, 92]
10 | y2 = [77, 79, 74, 82, 73, 78, 75, 85, 83, 81]
11 | y3 = [94, 93, 97, 89, 92, 97, 91, 85, 82, 96]
12 | y4 = [82, 81, 79, 85, 88, 73, 78, 82, 75, 79]
13 | y5 = [71, 78, 74, 73, 79, 77, 75, 74, 75, 81]
14 | y6 = [62, 65, 72, 66, 78, 73, 66, 68, 61, 63]
15 |
16 | # 绘制箱线图
17 | # 注意用yi生成各科的[min, Q2, mid, Q1, max]数据,用于后续绘制箱线图
18 | # 绘图的其它需求
19 | # 1. 主题为马卡龙画风(macarons)
20 | # 2. 让箱线图的须更长,数据分布更易于观察:把y轴的最小值设为数据的最小值,而不是从0开始
21 | # (这一步怎么设置的,建议查一下文档,写得明明白白)
22 | # 3. 全图标题“各科成绩”
23 | boxplot = (
24 | Boxplot(init_opts=opts.InitOpts(theme="macarons"))
25 | .set_global_opts(
26 | title_opts=opts.TitleOpts(title="各科成绩"),
27 | yaxis_opts=opts.AxisOpts(min_="dataMin") # dataMin怎么来的,官方文档上去查,写得明明白白
28 | )
29 | .add_xaxis(xaxis_data=xData)
30 | )
31 | # 添加y轴数据
32 | boxplot.add_yaxis(
33 | series_name="",
34 | y_axis=boxplot.prepare_data([y1, y2, y3, y4, y5, y6])
35 | )
36 | # 保存路径
37 | resultPath = "./result"
38 | if not os.path.exists(path=resultPath):
39 | os.mkdir(path=resultPath)
40 | # 保存文件名
41 | resultFileName = "scores_boxplot.html"
42 | # 执行保存
43 | boxplot.render(path=os.path.join(resultPath, resultFileName))
44 |
--------------------------------------------------------------------------------
/12数据分布之箱线图/example12_3/example12_3.py:
--------------------------------------------------------------------------------
1 | # 探究泰坦尼克号不同等级船舱的乘客年龄分布情况
2 | import os
3 | import openpyxl
4 | from openpyxl import Workbook
5 | from openpyxl.worksheet.worksheet import Worksheet
6 | from pyecharts.charts import Boxplot
7 | import pyecharts.options as opts
8 |
9 | # 资源文件目录
10 | resourcesPath = "./resources"
11 | # 泰坦尼克号遇难者名单
12 | titanicBookName = "titanic.xlsx"
13 | # 乘客名单工作表
14 | passengerSheetName = "passenger"
15 | # 打开文件、选表
16 | passengerSheet = openpyxl.load_workbook(
17 | filename=os.path.join(resourcesPath, titanicBookName)
18 | )[passengerSheetName] # type: Worksheet
19 |
20 | # 选择[船舱等级, 年龄]两列的数据,提取这两列的原始数据
21 | orgData = [
22 | [row_item[1], row_item[4]]
23 | for row_item in passengerSheet.iter_rows(min_row=2, values_only=True)
24 | ]
25 |
26 |
27 | # 处理绘图用的数据
28 | plotData = {
29 | "一等舱": [],
30 | "二等舱": [],
31 | "三等舱": []
32 | }
33 | # 扫描原始数据
34 | for pClass, age in orgData:
35 | if pClass == 1:
36 | plotData["一等舱"].append(age)
37 | elif pClass == 2:
38 | plotData["二等舱"].append(age)
39 | elif pClass == 3:
40 | plotData["三等舱"].append(age)
41 |
42 |
43 | # 绘制船舱等级与年龄关系的箱线图,需求:
44 | # 1. 主题为light
45 | # 2. 标题为“舱位与年龄的分布”
46 | # 3. y轴起点是上述y轴所有数据的最小值
47 | boxplot = (
48 | Boxplot(init_opts=opts.InitOpts(theme="light"))
49 | .set_global_opts(
50 | title_opts=opts.TitleOpts(title="舱位与年龄的分布"),
51 | yaxis_opts=opts.AxisOpts(min_="dataMin")
52 | )
53 | .add_xaxis(xaxis_data=list(plotData.keys()))
54 | )
55 | # 获取箱线图y轴[min, Q2, mid, Q1, max]序列
56 | yData = boxplot.prepare_data(items=[plot_value for plot_value in plotData.values()])
57 | print(yData)
58 | boxplot.add_yaxis(
59 | series_name="",
60 | y_axis=yData
61 | )
62 |
63 | # 保存路径
64 | resultPath = "./result"
65 | if not os.path.exists(path=resultPath):
66 | os.mkdir(path=resultPath)
67 | # 保存文件名
68 | resultFileName = "titanic_boxplot.html"
69 | # 执行保存
70 | boxplot.render(path=os.path.join(resultPath, resultFileName))
71 |
--------------------------------------------------------------------------------
/12数据分布之箱线图/example12_3/resources/titanic.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/12数据分布之箱线图/example12_3/resources/titanic.xlsx
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_1/example13_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 |
5 | # 用桑基图表达月度开支的钱的各种去向
6 |
7 | # 准备桑基图的原始数据(节点、信息流),跳过从excel中读取数据的过程
8 | # 节点列表:格式[{"name": 标签名1}, {“name”: 标签名2}, ...]
9 | nodes = [
10 | {"name": "围巾"},
11 | {"name": "长辈"},
12 | {"name": "网络费"},
13 | {"name": "服装"},
14 | {"name": "公交"},
15 | {"name": "同学"},
16 | {"name": "袜子"},
17 | {"name": "总费用"},
18 | {"name": "衣服"},
19 | {"name": "红包"},
20 | {"name": "交通"},
21 | {"name": "聚餐"},
22 | {"name": "滴滴"},
23 | {"name": "餐饮"},
24 | {"name": "管理费"},
25 | {"name": "水电"},
26 | {"name": "共享单车"},
27 | {"name": "外卖"},
28 | {"name": "房租"},
29 | {"name": "住宿"},
30 | {"name": "饮料"},
31 | {"name": "鞋子"},
32 | {"name": "地铁"}
33 | ]
34 | # 信息流列表:格式
35 | # [{"source": 标签名1, "target": 标签名1, "value": 取值1},
36 | # {"source": 标签名2, "target": 标签名2, "value": 取值2},
37 | # ......]
38 | links = [
39 | {"source": "总费用", "target": "住宿", "value": 2580},
40 | {"source": "总费用", "target": "餐饮", "value": 1300},
41 | {"source": "总费用", "target": "交通", "value": 500},
42 | {"source": "总费用", "target": "服装", "value": 900},
43 | {"source": "总费用", "target": "红包","value": 1300},
44 | {"source": "住宿", "target": "房租", "value": 2000},
45 | {"source": "住宿", "target": "水电", "value": 400},
46 | {"source": "住宿", "target": "管理费", "value": 100},
47 | {"source": "住宿", "target": "网络费", "value": 80},
48 | {"source": "餐饮", "target": "外卖", "value": 800},
49 | {"source": "餐饮", "target": "聚餐", "value": 300},
50 | {"source": "餐饮", "target": "饮料", "value": 200},
51 | {"source": "交通", "target": "滴滴", "value": 220},
52 | {"source": "交通", "target": "地铁", "value": 150},
53 | {"source": "交通", "target": "公交", "value": 80},
54 | {"source": "交通", "target": "共享单车", "value": 50},
55 | {"source": "服装", "target": "衣服", "value": 400},
56 | {"source": "服装", "target": "鞋子", "value": 300},
57 | {"source": "服装", "target": "围巾", "value": 150},
58 | {"source": "服装", "target": "袜子", "value": 50},
59 | {"source": "红包", "target": "同学", "value": 800},
60 | {"source": "红包", "target": "长辈", "value": 500}
61 | ]
62 |
63 | # 桑基图绘图的需求:
64 | # 1. 根据开支明细,按照节点和信息流列表结构,直接创建数据的节点和信息流列表;
65 | # 2. 绘制桑基图,系列名称为"月度开支"
66 | # 3. 数据标签统一放在节点右边
67 | # 4. 保存图片
68 | # 5. 这个图绘制出来肯定特别丑,所以后面还会改进
69 | # 保存路径
70 | resultPath = "./result"
71 | if not os.path.exists(path=resultPath):
72 | os.mkdir(path=resultPath)
73 | # 保存文件名
74 | resultFileName = "purchase_sankey.html"
75 | # 执行绘图
76 | sankey = (
77 | Sankey()
78 | .add(
79 | series_name="月度开支",
80 | nodes=nodes,
81 | links=links,
82 | label_opts=opts.LabelOpts(position="right")
83 | )
84 | .render(path=os.path.join(resultPath, resultFileName))
85 | )
86 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_2/example13_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 |
5 | # 使用桑基图直观表达创意馆产品不同类型产品的数量
6 |
7 | # 准备原始数据(节点、信息流),暂时略去从表中读取出数据的过程
8 | # 节点列表
9 | nodes = [
10 | {"name": "遥控"},
11 | {"name": "非遥控"},
12 | {"name": "机器人"},
13 | {"name": "猛击赛车"},
14 | {"name": "莱肯赛车"}
15 | ]
16 | # 信息流列表
17 | links = [
18 | {"source": "遥控", "target": "机器人", "value": 15},
19 | {"source": "遥控", "target": "猛击赛车", "value": 23},
20 | {"source": "遥控", "target": "莱肯赛车", "value": 36},
21 | {"source": "非遥控", "target": "机器人", "value": 48},
22 | {"source": "非遥控", "target": "猛击赛车", "value": 21},
23 | {"source": "非遥控", "target": "莱肯赛车", "value": 11}
24 | ]
25 |
26 | # 绘制桑基图要求
27 | # 1. 数据系列名称为空
28 | # 2. 添加数据标签放在节点右边;
29 | # 3. 全图标题"馆内产品分类";
30 | # 4. 保存图片
31 | # 5. 图片很丑,后面再操心怎么优化
32 | # 保存路径
33 | resultPath = "./result"
34 | if not os.path.exists(path=resultPath):
35 | os.mkdir(path=resultPath)
36 | # 保存文件名
37 | resultFileName = "product_category_sankey.html"
38 | # 执行绘图
39 | sankey = (
40 | Sankey()
41 | .set_global_opts(title_opts=opts.TitleOpts(title="馆内产品分类"))
42 | .add(
43 | series_name="",
44 | nodes=nodes,
45 | links=links,
46 | label_opts=opts.LabelOpts(position="right")
47 | )
48 | .render(path=os.path.join(resultPath, resultFileName))
49 | )
50 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_2/result/product_category_sankey.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_3/example13_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 |
5 | # 在example13_2基础上再进一步,使用桑基图直观表达创意馆产品不同分类的产品销售情况
6 |
7 | # 准备原始数据(节点、信息流),省略从表格中读进数据的步骤
8 | # 数据节点列表
9 | nodes = [
10 | {"name": "机器人"},
11 | {"name": "猛击赛车"},
12 | {"name": "莱肯赛车"},
13 | {"name": "遥控机器人"},
14 | {"name": "遥控猛击赛车"},
15 | {"name": "遥控莱肯赛车"},
16 | {"name": "非遥控机器人"},
17 | {"name": "非遥控猛击赛车"},
18 | {"name": "非遥控莱肯赛车"},
19 | {"name": "未购买"},
20 | {"name": "购买"}
21 | ]
22 | # 信息流列表
23 | links = [
24 | {"source": "机器人", "target": "遥控机器人", "value": 12},
25 | {"source": "机器人", "target": "非遥控机器人", "value": 32},
26 | {"source": "猛击赛车", "target": "遥控猛击赛车", "value": 23},
27 | {"source": "猛击赛车", "target": "非遥控猛击赛车", "value": 11},
28 | {"source": "莱肯赛车", "target": "遥控莱肯赛车", "value": 45},
29 | {"source": "莱肯赛车", "target": "非遥控莱肯赛车", "value": 12},
30 | {"source": "遥控机器人", "target": "未购买", "value": 12},
31 | {"source": "遥控猛击赛车", "target": "购买", "value": 23},
32 | {"source": "遥控莱肯赛车", "target": "未购买", "value": 45},
33 | {"source": "非遥控机器人", "target": "购买", "value": 32},
34 | {"source": "非遥控猛击赛车", "target": "未购买", "value": 11},
35 | {"source": "非遥控莱肯赛车", "target": "购买", "value": 12}
36 | ]
37 |
38 | # 绘制桑基图需求
39 | # 1. 数据系列名称设置为空
40 | # 2. 数据标签放在节点右边
41 | # 3. 图表标题为“馆内产品售卖”
42 | # 4. 保存
43 | # 5. 图可能会很丑,美化的事情后面再操心
44 | # 保存路径
45 | resultPath = "./result"
46 | if not os.path.exists(path=resultPath):
47 | os.mkdir(path=resultPath)
48 | # 保存文件名
49 | resultFileName = "product_sales_sankey.html"
50 | sankey = (
51 | Sankey()
52 | .set_global_opts(title_opts=opts.TitleOpts(title="馆内产品售卖"))
53 | .add(
54 | series_name="",
55 | nodes=nodes,
56 | links=links,
57 | label_opts=opts.LabelOpts(position="right"),
58 | linestyle_opt=opts.LineStyleOpts(color="#FFF0F5")
59 | )
60 | )
61 | # 执行保存
62 | sankey.render(path=os.path.join(resultPath, resultFileName))
63 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_4/example13_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 |
5 | # 使用三维桑基图(性别-熬夜原因-人数)直观描述当代青年人熬夜的原因分布情况
6 |
7 | # 准备原始数据(节点、信息流),从表中取数据的过程略去
8 | # 节点
9 | nodes = [
10 | {"name": "男"},
11 | {"name": "女"},
12 | {"name": "打游戏"},
13 | {"name": "加班"},
14 | {"name": "看剧"}
15 | ]
16 | # 信息流
17 | links = [
18 | {"source": "男", "target": "打游戏", "value": 79},
19 | {"source": "男", "target": "加班", "value": 13},
20 | {"source": "男", "target": "看剧", "value": 24},
21 | {"source": "女", "target": "打游戏", "value": 16},
22 | {"source": "女", "target": "加班", "value": 5},
23 | {"source": "女", "target": "看剧", "value": 63}
24 | ]
25 |
26 | # 绘制桑基图需求
27 | # 1. 主题为light
28 | # 2. 标题为“当代青年熬夜原因”
29 | # 3. 隐藏图例
30 | # 4. 美化图片:信息流透明度为20%,弯曲度50%,颜色取目标节点的颜色(这种特殊值怎么取,查官方文档)
31 | # 5. 标签放在节点右侧,颜色设置为黑色
32 | # 6. 保存图片
33 | # 保存路径
34 | resultPath = "./result"
35 | if not os.path.exists(path=resultPath):
36 | os.mkdir(path=resultPath)
37 | # 保存文件名
38 | resultFileName = "stayup_reason_sankey.html"
39 | # 执行绘图
40 | sankey = (
41 | Sankey(init_opts=opts.InitOpts(theme="light"))
42 | .set_global_opts(
43 | title_opts=opts.TitleOpts(title="当代青年熬夜原因"),
44 | legend_opts=opts.LegendOpts(is_show=False)
45 | )
46 | .add(
47 | series_name="",
48 | nodes=nodes,
49 | links=links,
50 | linestyle_opt=opts.LineStyleOpts(
51 | opacity=0.2,
52 | curve=0.5,
53 | color="target" # 取目标节点的颜色
54 | ),
55 | label_opts=opts.LabelOpts(
56 | color="rgb(0, 0, 0)", # 或者写成#000000
57 | position="right"
58 | )
59 | )
60 | )
61 | # 执行保存
62 | sankey.render(path=os.path.join(resultPath, resultFileName))
63 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_4/result/stayup_reason_sankey.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Awesome-pyecharts
6 |
7 |
8 |
9 |
10 |
11 |
144 |
145 |
146 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_5/example13_5.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 | from pyecharts.globals import ThemeType
5 |
6 | # 桑基图直观表达宠物店商品的购买路径
7 |
8 | # 准备绘制桑基图需要的数据(节点、数据流),省略从文件中取出数据的过程
9 | # 创建节点列表
10 |
11 | nodes = [
12 | {"name": "狗粮"},
13 | {"name": "玩具"},
14 | {"name": "1-小规格狗粮"},
15 | {"name": "1-大规格狗粮"},
16 | {"name": "1-磨牙棒"},
17 | {"name": "2-未购买"},
18 | {"name": "2-小规格狗粮"},
19 | {"name": "2-大规格狗粮"},
20 | {"name": "2-磨牙棒"},
21 | ]
22 | # 创建信息流列表
23 | links = [
24 | {"source": "狗粮", "target": "1-小规格狗粮", "value": 613},
25 | {"source": "狗粮", "target": "1-大规格狗粮", "value": 1018},
26 | {"source": "玩具", "target": "1-磨牙棒", "value": 197},
27 | {"source": "1-小规格狗粮", "target": "2-未购买", "value": 654},
28 | {"source": "1-小规格狗粮", "target": "2-磨牙棒", "value": 21},
29 | {"source": "1-小规格狗粮", "target": "2-小规格狗粮", "value": 231},
30 | {"source": "1-小规格狗粮", "target": "2-大规格狗粮", "value": 112},
31 | {"source": "1-大规格狗粮", "target": "2-未购买", "value": 375},
32 | {"source": "1-大规格狗粮", "target": "2-磨牙棒", "value": 23},
33 | {"source": "1-大规格狗粮", "target": "2-小规格狗粮", "value": 18},
34 | {"source": "1-大规格狗粮", "target": "2-大规格狗粮", "value": 197},
35 | {"source": "1-磨牙棒", "target": "2-未购买", "value": 157},
36 | {"source": "1-磨牙棒", "target": "2-磨牙棒", "value": 3},
37 | {"source": "1-磨牙棒", "target": "2-小规格狗粮", "value": 24},
38 | {"source": "1-磨牙棒", "target": "2-大规格狗粮", "value": 13},
39 | ]
40 |
41 | # 绘制桑基图的需求
42 | # 1. 主题设为essos风格
43 | # 2. 标题为“购买路径”
44 | # 3. 图例隐藏
45 | # 4. 信息流设为垂直方向(参考下官方文档里的参数设置)
46 | # 5. 标签在节点上方,颜色为黑色
47 | # 6. 美化图片:信息流透明度为0.3,弯曲度为0.5,颜色与目标节点颜色一致
48 | # 7. 保存图片
49 | # 保存路径
50 | resultPath = "./result"
51 | if not os.path.exists(path=resultPath):
52 | os.mkdir(path=resultPath)
53 | # 保存文件名
54 | resultFileName = "pet_sales_sankey.html"
55 | # 执行绘图
56 | sankey = (
57 | Sankey(init_opts=opts.InitOpts(theme=ThemeType.ESSOS))
58 | .set_global_opts(
59 | title_opts=opts.TitleOpts(title="购买路径"),
60 | legend_opts=opts.LegendOpts(is_show=False)
61 | )
62 | .add(
63 | series_name="",
64 | nodes=nodes,
65 | links=links,
66 | orient="vertical",
67 | linestyle_opt=opts.LineStyleOpts(
68 | opacity=0.3,
69 | curve=0.5,
70 | color="target"
71 | ),
72 | label_opts=opts.LabelOpts(
73 | position="top",
74 | color="#000000"
75 | )
76 | )
77 | )
78 | # 执行保存
79 | sankey.render(path=os.path.join(resultPath, resultFileName))
80 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_6/example13_6.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Sankey
3 | import pyecharts.options as opts
4 | import openpyxl
5 | from openpyxl.workbook.workbook import Workbook
6 | from openpyxl.worksheet.worksheet import Worksheet
7 |
8 | # 使用桑基图,直观描述一个人的年度歌单下不同类目的歌曲的数量构成
9 |
10 |
11 | # 配置信息
12 |
13 | # 资源文件夹
14 | resourcesPath = "./resources"
15 | # 歌单数据文件
16 | songListBookName = "song.xlsx"
17 | # 歌单工作表名
18 | songListSheetName = "年度歌单"
19 | # 打开歌单数据表
20 | songListSheet = openpyxl.load_workbook(
21 | filename=os.path.join(resourcesPath, songListBookName)
22 | )[songListSheetName] # type: Worksheet
23 |
24 |
25 | # 按照格式生成桑基图的节点数据字典
26 | def sankey_node(node_name: str) -> dict:
27 | """
28 | 绘制桑基图节点的固定格式{"name": node_name}
29 |
30 | :param node_name: 节点名称
31 |
32 | :return: 绘制桑基图固定节点格式{"name": node_name}
33 | """
34 | return {"name": node_name}
35 |
36 |
37 | # 按照格式生成桑基图的信息流数据字典
38 | def sankey_link(source_name: str, target_name: str, val: float) -> dict:
39 | """
40 |
41 | 绘制桑基图节点的固定格式{"source": src_name, "target": target_name, "value": val}
42 |
43 | :param source_name: 信息流源节点的名称
44 |
45 | :param target_name: 信息流目标节点的名称
46 |
47 | :param val: 信息流权重(多少数据在这个信息流上)
48 |
49 | :return: {"source": src_name, "target": target_name, "value": val}
50 | """
51 | return {"source": source_name, "target": target_name, "value": val}
52 |
53 |
54 | # 准备原始数据:先把表格内容都读进来
55 | orgData = [row_item for row_item in songListSheet.iter_rows(min_row=2, values_only=True)]
56 | # print(orgData)
57 | # 准备绘图用数据:节点列表和信息流列表
58 | nodes = []
59 | links = []
60 |
61 |
62 | # 扫描各行,添加节点原始数据
63 | for songItem in orgData:
64 | nodes.extend(list(songItem[:-1]))
65 | # 节点去重
66 | nodes = list(set(nodes))
67 | # 修饰每个节点数据,改造成符合sankey绘图格式的字典格式
68 | for songIndex, songTypeItem in enumerate(nodes):
69 | nodes[songIndex] = sankey_node(node_name=songTypeItem)
70 |
71 |
72 | # 根据原始数据生成信息流,添加至列表
73 | for songType in orgData:
74 | # 把取值拎出来
75 | val = songType[-1]
76 | # 一共有多少个分级类目
77 | levelCount = len(songType[0:-1])
78 | # 考虑多个分级的通用情况
79 | for level in range(levelCount-1):
80 | # 当前分级和下一分级之间存在一个信息流
81 | links.append(
82 | sankey_link(
83 | source_name=songType[level],
84 | target_name=songType[level + 1],
85 | val=val)
86 | )
87 |
88 | # print(nodes)
89 | # print(links)
90 |
91 |
92 | # 绘制桑基图的需求
93 | # 1. 主题为dark
94 | # 2. 背景色为#253441
95 | # 3. 标题为“年度歌单”
96 | # 4. 隐藏图例
97 | # 5. 美化图片:信息流的透明度为30%,弯曲度50%,颜色与源节点统一一致(有一个特殊值,查官方文档说了)
98 | # 6. 数据标签字体10,放节点右侧,颜色为白色#FFFFFF
99 | # 7. 保存图片
100 | # 保存路径
101 | resultPath = "./result"
102 | if not os.path.exists(path=resultPath):
103 | os.mkdir(path=resultPath)
104 | # 保存文件名
105 | resultFileName = "songList_sankey.html"
106 | # 执行绘图
107 | sankey = (
108 | Sankey(
109 | init_opts=opts.InitOpts(
110 | theme="dark",
111 | bg_color="#253441"
112 | )
113 | )
114 | .set_global_opts(
115 | title_opts=opts.TitleOpts(title="年度歌单"),
116 | legend_opts=opts.LegendOpts(is_show=False)
117 | )
118 | .add(
119 | series_name="",
120 | nodes=nodes,
121 | links=links,
122 | linestyle_opt=opts.LineStyleOpts(
123 | opacity=0.3,
124 | curve=0.5,
125 | color="source"
126 | ),
127 | label_opts=opts.LabelOpts(
128 | font_size=10,
129 | position="right",
130 | color="#FFFFFF"
131 | )
132 | )
133 | )
134 | # 执行保存
135 | sankey.render(path=os.path.join(resultPath, resultFileName))
136 |
--------------------------------------------------------------------------------
/13数据流向之桑基图/example13_6/resources/song.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/13数据流向之桑基图/example13_6/resources/song.xlsx
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_1/example14_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl.workbook.workbook import Workbook
4 | from openpyxl.worksheet.worksheet import Worksheet
5 | from pyecharts.charts import Scatter
6 | import pyecharts.options as opts
7 |
8 | # 用散点图描述电竞游戏职业玩家WJ.TS的100局游戏中,经济占比对输出占比影响的相关性
9 |
10 | # 基础参数
11 | # 资源文件所在目录
12 | resourcesPath = "./resources"
13 | # 职业玩家的游戏数据文件
14 | gameBookName = "wj.xlsx"
15 | # 工作表名称
16 | gameSheetName = "选手数据"
17 |
18 | # 取出输出和经济数据,因为原表结构不是很好,代码不是很讲究复用性
19 | wb = openpyxl.load_workbook(filename=os.path.join(resourcesPath, gameBookName)) # type: Workbook
20 | sheet = wb[gameSheetName] # type: Worksheet
21 | # 100局游戏的输出数据,作为x轴
22 | attack_list = []
23 | # 100局游戏的经济数据,作为y轴
24 | income_list = []
25 | for attackCell, incomeCell in zip(sheet["K"], sheet["M"]):
26 | attack_list.append(attackCell.value)
27 | income_list.append(incomeCell.value)
28 |
29 | # 截取出WJ.TS的输出数据
30 | attack_list = attack_list[1:101]
31 | # 截取出WJ.TS的经济数据
32 | income_list = income_list[1:101]
33 | # print(attack_list)
34 | # print(income_list)
35 |
36 | # 散点图绘制需求
37 | # 1. x轴的数据不是用作零散的数据项,而是作为取值,注意设定x轴类型(查文档)
38 | # 2. 散点数据的标签要隐藏
39 | # 3. x轴名为"经济占比",y轴名为"伤害占比"
40 | # 4. 标题"输出占比与经济占比之间的关系"
41 | # 5. 保存
42 | # 保存路径
43 | resultPath = "./result"
44 | if not os.path.exists(path=resultPath):
45 | os.mkdir(path=resultPath)
46 | # 保存文件名
47 | resultFileName = "attack_income_scatter.html"
48 | # 执行绘图
49 | scatter = (
50 | Scatter()
51 | .set_global_opts(
52 | title_opts=opts.TitleOpts(title="输出占比与经济占比之间的关系"),
53 | xaxis_opts=opts.AxisOpts(name="经济占比", type_="value"),
54 | yaxis_opts=opts.AxisOpts(name="伤害占比")
55 | )
56 | .add_xaxis(xaxis_data=income_list)
57 | .add_yaxis(
58 | series_name="伤害-经济相关性",
59 | y_axis=attack_list,
60 | label_opts=opts.LabelOpts(is_show=False)
61 | )
62 | .render(path=os.path.join(resultPath, resultFileName))
63 | )
64 |
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_1/resources/wj.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/14相关与分布之散点图/example14_1/resources/wj.xlsx
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_2/example14_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Scatter
3 | import pyecharts.options as opts
4 | import openpyxl
5 | from openpyxl.workbook.workbook import Workbook
6 | from openpyxl.worksheet.worksheet import Worksheet
7 |
8 | # 资源目录
9 | resourcesPath = "./resources"
10 | # 日均销量对比工作表名
11 | dailySalesBookName = "日均销量对比.xlsx"
12 | # 选中工作表
13 | wb = openpyxl.load_workbook(filename=os.path.join(resourcesPath, dailySalesBookName)) # type: Workbook
14 | sheet = wb["销量对比"] # type: Worksheet
15 |
16 | # 取出阿珍和竞品商的销售数据(因为本身这个表结构不是特别好,所以读的话就按照下面毫无复用性的烂代码读吧)
17 | # 取出需要对比的商品名称(作为x轴)
18 | name_list = []
19 | for cell in sheet["B"][1:7]:
20 | name_list.append(cell.value)
21 |
22 | # 将商品销量这一列数据全部提取出
23 | sales_list = []
24 | for cell in sheet["C"]:
25 | sales_list.append(cell.value)
26 | # 阿珍的数据sales_azhen(y轴数据1)
27 | sales_azhen = sales_list[1:7]
28 | # 竞品的数据sales_competitor(y轴数据2)
29 | sales_competitor = sales_list[7:13]
30 |
31 | # 绘制散点图需求
32 | # 1. 标题“日均销量对比”
33 | # 2. 阿珍的数据用点表示,竞品数据用菱形表示(查官方文档找参数)
34 | # 3. 添加视觉映设,最大映射取350,最小映射取20,数据大小通过视觉映射的大小体现(查文档找参数)
35 | # 4. 图例系列名分别为“阿珍”和“竞品”
36 | # 5. 设置x轴名称为“商品”,y轴名称为“销量”
37 | # 6. 保存文件
38 | # 保存路径
39 | resultPath = "./result"
40 | if not os.path.exists(path=resultPath):
41 | os.mkdir(path=resultPath)
42 | # 保存文件名
43 | resultFileName = "product_competitor_scatter.html"
44 | # 执行绘图
45 | scatter = (
46 | Scatter()
47 | .set_global_opts(
48 | title_opts=opts.TitleOpts(title="日均销量对比"),
49 | visualmap_opts=opts.VisualMapOpts(
50 | max_=350,
51 | min_=20,
52 | type_="size"
53 | ),
54 | xaxis_opts=opts.AxisOpts(name="商品"),
55 | yaxis_opts=opts.AxisOpts(name="销量")
56 | )
57 | .add_xaxis(xaxis_data=name_list)
58 | .add_yaxis(
59 | series_name="阿珍",
60 | y_axis=sales_azhen
61 | )
62 | .add_yaxis(
63 | series_name="竞品",
64 | y_axis=sales_competitor,
65 | symbol="diamond"
66 | )
67 | )
68 | # 执行保存
69 | scatter.render(path=os.path.join(resultPath, resultFileName))
70 |
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_2/resources/日均销量对比.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/14相关与分布之散点图/example14_2/resources/日均销量对比.xlsx
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_3/example14_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Scatter, Tab
3 | import pyecharts.options as opts
4 | from pyecharts.globals import ThemeType
5 | import openpyxl
6 | from openpyxl.workbook.workbook import Workbook
7 | from openpyxl.worksheet.worksheet import Worksheet
8 |
9 | # 散点图画下面几组很有趣的数据,放在看板里面
10 | # Alberto Cairo教授曾经构造的5组数据文件
11 | # 这5组文件很有特点:x系列数值平均数相同,标准差相同,相关系数也相同;y系列数值亦然
12 | # 但绘制出的散点图却完全不同
13 |
14 | # 资源文件目录
15 | resourcesPath = "./resources"
16 | # 工作文件名
17 | acBookName = "dino1.xlsx"
18 | # 工作表名
19 | acSheetName = "数据"
20 |
21 | # 打开文件选表
22 | acSheet = openpyxl.load_workbook(filename=os.path.join(resourcesPath, acBookName))[acSheetName] # type: Worksheet
23 |
24 | # 逐列扫描提出数据,跳过表头
25 | orgData = [list(col_item) for col_item in acSheet.iter_cols(min_row=3, values_only=True)]
26 | print(orgData)
27 |
28 | # 提取各列用于绘制散点图的数据
29 | awayX = orgData[0]
30 | awayY = orgData[1]
31 | bullseyeX = orgData[2]
32 | bullseyeY = orgData[3]
33 | circleX = orgData[4]
34 | circleY = orgData[5]
35 | dinoX = orgData[6]
36 | dinoY = orgData[7]
37 | dotsX = orgData[8]
38 | dotsY = orgData[9]
39 |
40 |
41 | def scat_plot(x_data, y_data) -> Scatter:
42 | """
43 | 用于绘制散点图的x轴和y轴数据
44 |
45 | 1. 画布宽度为"1000px",高度为"600px",主题为"light"
46 |
47 | 2. 隐藏y轴的数据标签
48 |
49 | 3. x轴的坐标应该是连续型
50 |
51 | :param x_data: x轴数据
52 |
53 | :param y_data: y轴数据
54 |
55 | :return: 画好的散点图对象,用于后续添加到看板中
56 | """
57 | scatter = (
58 | Scatter(init_opts=opts.InitOpts(theme=ThemeType.LIGHT, width="1000px", height="600px"))
59 | .set_global_opts(xaxis_opts=opts.AxisOpts(type_="value"))
60 | .add_xaxis(xaxis_data=x_data)
61 | .add_yaxis(
62 | series_name="",
63 | y_axis=y_data,
64 | label_opts=opts.LabelOpts(is_show=False)
65 | )
66 | )
67 | return scatter
68 |
69 |
70 | # 逐个执行绘图,添加到看板中,并保存
71 | # 保存路径
72 | resultPath = "./result"
73 | if not os.path.exists(path=resultPath):
74 | os.mkdir(path=resultPath)
75 | # 文件名
76 | resultFileName = "acplot_scatter.html"
77 | # 执行绘图和保存
78 | tab = (
79 | Tab()
80 | .add(chart=scat_plot(x_data=awayX, y_data=awayY), tab_name="away")
81 | .add(chart=scat_plot(x_data=bullseyeX, y_data=bullseyeY), tab_name="bullseye")
82 | .add(chart=scat_plot(x_data=circleX, y_data=circleY), tab_name="circle")
83 | .add(chart=scat_plot(x_data=dinoX, y_data=dinoY), tab_name="dino")
84 | .add(chart=scat_plot(x_data=dotsX, y_data=dotsY), tab_name="dots")
85 | .render(path=os.path.join(resultPath, resultFileName))
86 | )
87 |
--------------------------------------------------------------------------------
/14相关与分布之散点图/example14_3/resources/dino1.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/14相关与分布之散点图/example14_3/resources/dino1.xlsx
--------------------------------------------------------------------------------
/15综合评估之雷达图/example15_1/example15_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Radar
3 | import pyecharts.options as opts
4 |
5 | # 使用雷达图,综合评估两地的各种空气指标
6 | # [AQI(空气质量指数), PM2.5, PM10, CO, NO2, SO2]
7 |
8 | # 准备绘图用的初始顺序
9 | # 构造A城市多日空气情况的二维数据表
10 | A = [
11 | [55, 9, 56, 0.46, 18, 6],
12 | [25, 11, 21, 0.65, 34, 9],
13 | [56, 7, 63, 0.3, 14, 5],
14 | [33, 7, 29, 0.33, 16, 6],
15 | [42, 24, 44, 0.76, 40, 16],
16 | [82, 58, 90, 1.77, 68, 33],
17 | [74, 49, 77, 1.46, 48, 27],
18 | [78, 55, 80, 1.29, 59, 29],
19 | [267, 216, 280, 4.8, 108, 64],
20 | [185, 127, 216, 2.52, 61, 27],
21 | [39, 19, 38, 0.57, 31, 15],
22 | [41, 11, 40, 0.43, 21, 7],
23 | ]
24 | # 构造B城市多日空气情况的二维数据表
25 | B = [
26 | [91, 45, 125, 0.82, 34, 23],
27 | [65, 27, 78, 0.86, 45, 29],
28 | [83, 60, 84, 1.09, 73, 27],
29 | [109, 81, 121, 1.28, 68, 51],
30 | [106, 77, 114, 1.07, 55, 51],
31 | [109, 81, 121, 1.28, 68, 51],
32 | [106, 77, 114, 1.07, 55, 51],
33 | [89, 65, 78, 0.86, 51, 26],
34 | [53, 33, 47, 0.64, 50, 17],
35 | [80, 55, 80, 1.01, 75, 24],
36 | [117, 81, 124, 1.03, 45, 24],
37 | [99, 71, 142, 1.1, 62, 42],
38 | ]
39 |
40 | # 绘制雷达图的需求
41 | # 1. 坐标轴一共有6个维度,每个维度取名为相应空气指标的名字,每个维度限制合理的最大值和最小值
42 | # 2. 坐标轴整体为圆形
43 | # 3. A市的图例系列名称为“A市”,B市同理;颜色分别为#6495ed和#ff8c00
44 | # 4. 不显示数据标签
45 | # 5. 标题为"空气质量对比"
46 | # 6. 执行保存
47 | # 保存路径
48 | resultPath = "./result"
49 | if not os.path.exists(path=resultPath):
50 | os.mkdir(path=resultPath)
51 | # 保存文件名
52 | resultFileName = "air_quality_radar.html"
53 | # 按照格式设置坐标轴(schema)属性
54 | c_schema = [
55 | opts.RadarIndicatorItem(name="AQI", max_=300, min_=5),
56 | opts.RadarIndicatorItem(name="PM2.5", max_=250, min_=20),
57 | opts.RadarIndicatorItem(name="PM10", max_=300, min_=5),
58 | opts.RadarIndicatorItem(name="CO", max_=5),
59 | opts.RadarIndicatorItem(name="NO2", max_=200),
60 | opts.RadarIndicatorItem(name="SO2", max_=100)
61 | # 等价于用字典创建
62 | # {"name": "AQI", "max": 300, "min": 5},
63 | # {"name": "PM2.5", "max": 250, "min": 20},
64 | # {"name": "PM10", "max": 300, "min": 5},
65 | # {"name": "CO", "max": 5},
66 | # {"name": "NO2", "max": 200},
67 | # {"name": "SO2", "max": 100}
68 | ]
69 | # 执行绘图
70 | radar = (
71 | Radar()
72 | .set_global_opts(title_opts=opts.TitleOpts(title="空气质量对比"))
73 | .add_schema(schema=c_schema, shape="circle")
74 | .add(
75 | series_name="A市",
76 | data=A,
77 | label_opts=opts.LabelOpts(is_show=False),
78 | color="#6495ed"
79 | )
80 | .add(
81 | series_name="B市",
82 | data=B,
83 | label_opts=opts.LabelOpts(is_show=False),
84 | color="#ff8c00"
85 | )
86 | .render(path=os.path.join(resultPath, resultFileName))
87 | )
88 |
--------------------------------------------------------------------------------
/15综合评估之雷达图/example15_2/example15_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts import options as opts
3 | from pyecharts.charts import Radar
4 |
5 | # 准备用于绘制雷达图的数据,省略从文件中读取的部分
6 | # 六个数据维度的数据是[传球, 射门, 体力, 防守, 速度, 盘带]
7 | # C·罗纳尔多的数据,并赋值给cl
8 | cl = [[83, 92, 87, 49, 89, 86]]
9 | # 梅西的数据,并赋值给mx
10 | mx = [[88, 95, 66, 43, 86, 96]]
11 | # 苏亚雷斯的数据
12 | sy = [[80, 92, 87, 58, 78, 81]]
13 | # 莱万多夫斯基的数据
14 | lw = [[79, 92, 84, 53, 81, 87]]
15 | # 列兹曼的数据
16 | gl = [[84, 87, 70, 54, 86, 89]]
17 |
18 | # 雷达图绘图需求
19 | # 1. 设置雷达的坐标系
20 | # 2. 雷达图的背景色为#dcdcdc
21 | # 3. 雷达图的宽、高分别为1000px和600px
22 | # 4. 雷达图的标题为"球员表现"
23 | # 5. 数据标签全部隐藏
24 | # 6. 雷达图围起来的区域要体现出颜色,透明度设置为1
25 | # 7. 取值:
26 | # 第一个球员的数据为:图例系列名称"C·罗纳尔多",数据值cl,颜色为#6495ed,并将数据标签隐藏
27 | # 第二个球员的数据为:图例系列名称"梅西",数据值mx,颜色为#ff8c00,并将数据标签隐藏
28 | # 第三个球员的数据为:图例系列名称"苏亚雷斯",数据值sy,颜色为#00ff00,并将数据标签隐藏
29 | # 第四个球员的数据为:图例系列名称"莱万多夫斯基",数据值lw,颜色为#a0522d,并将数据标签隐藏
30 | # 第五个球员的数据为:图例系列名称"格列兹曼",数据值gl,颜色为#da70d6,并将数据标签隐藏
31 | # 8. 保存图片
32 | # 保存路径
33 | resultPath = "./result"
34 | if not os.path.exists(path=resultPath):
35 | os.mkdir(path=resultPath)
36 | # 保存文件名
37 | resultFileName = "player_radar.html"
38 |
39 | # 设置雷达图的坐标系
40 | c_schema = [
41 | # 设置坐标轴名称"传球"和最大值100
42 | opts.RadarIndicatorItem(name="传球", max_=100),
43 | # 设置坐标轴名称"射门"和最大值100
44 | opts.RadarIndicatorItem(name="射门", max_=100),
45 | # 设置坐标轴名称"体力"和最大值100
46 | opts.RadarIndicatorItem(name="体力", max_=100),
47 | # 设置坐标轴名称"防守"和最大值100
48 | opts.RadarIndicatorItem(name="防守", max_=100),
49 | # 设置坐标轴名称"速度"和最大值100
50 | opts.RadarIndicatorItem(name="速度", max_=100),
51 | # 设置坐标轴名称"盘带"和最大值100
52 | opts.RadarIndicatorItem(name="盘带", max_=100)
53 | ]
54 |
55 | # 执行绘图
56 | radar = (
57 | Radar(
58 | init_opts=opts.InitOpts(
59 | bg_color="#dcdcdc",
60 | width="1000px",
61 | height="600px"
62 | )
63 | )
64 | .set_global_opts(title_opts=opts.TitleOpts(title="球员表现"))
65 | .add_schema(
66 | schema=c_schema,
67 | splitarea_opt=opts.SplitAreaOpts(
68 | is_show=True,
69 | areastyle_opts=opts.AreaStyleOpts(opacity=1)
70 | )
71 | )
72 | .add(
73 | series_name="C·罗纳尔多",
74 | data=cl,
75 | color="#6495ed",
76 | label_opts=opts.LabelOpts(is_show=False)
77 | )
78 | .add(
79 | series_name="梅西",
80 | data=mx,
81 | color="#ff8c00",
82 | label_opts=opts.LabelOpts(is_show=False)
83 | )
84 | .add(
85 | series_name="苏亚雷斯",
86 | data=sy,
87 | color="#00ff00",
88 | label_opts=opts.LabelOpts(is_show=False)
89 | )
90 | .add(
91 | series_name="莱万多夫斯基",
92 | data=lw,
93 | color="#a0522d",
94 | label_opts=opts.LabelOpts(is_show=False)
95 | )
96 | .add(
97 | series_name="格列兹曼",
98 | data=gl,
99 | color="#da70d6",
100 | label_opts=opts.LabelOpts(is_show=False)
101 | )
102 | .render(path=os.path.join(resultPath, resultFileName))
103 | )
104 |
--------------------------------------------------------------------------------
/15综合评估之雷达图/example15_3/example15_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | import openpyxl
3 | from openpyxl.worksheet.worksheet import Worksheet
4 | from openpyxl.workbook.workbook import Workbook
5 | from pyecharts.charts import Radar
6 | import pyecharts.options as opts
7 |
8 | # 用雷达图绘制看上去比较高大上的手机品牌多项指标综合评测
9 |
10 | # 配置项
11 | # 资源文件目录
12 | resourcesPath = "./resources"
13 | # 手机测评文件名
14 | phoneTestBookName = "test.xlsx"
15 | # 手机测评工作表名
16 | phoneTestSheetName = "测评数据"
17 |
18 | # 打开文件并选表
19 | phoneTestSheet = openpyxl.load_workbook(
20 | filename=os.path.join(resourcesPath, phoneTestBookName))[phoneTestSheetName] # type: Worksheet
21 | # 取出原始数据
22 | # 数据项一共有:["外观", "性能", "拍照", "系统", "屏幕"],表头无需读取
23 | orgData = [list(row_item) for row_item in phoneTestSheet.iter_rows(min_row=2, values_only=True)]
24 | # print(orgData)
25 | # 清洗取值为None的列
26 | for row_item in orgData:
27 | while None in row_item:
28 | row_item.remove(None)
29 |
30 | # 绘制雷达图需求
31 | # 1. 设置主题为"chalk";
32 | # 2. 标题设置为"Amy专业手机评测";
33 | # 3. 将图例列表布局设置为纵向,图例与最左侧容器的相对距离设置为10%,与底部的相对距离设置为50%
34 | # 4. 雷达图为圆形
35 | # 5. 雷达图坐标围起来的一圈(分隔区域配置项)透明度为1
36 | # 6. 坐标轴各个部分的名称为['外观', '性能', '拍照', '系统', '屏幕'],满分均为10分
37 | # 7. 对于各种手机的取值设置:均隐藏数据标签,围起来的区域填充透明度为0.1
38 | # 图例系列名“华为”,颜色#800080
39 | # 图例系列名“OPPO”,颜色#6495ed
40 | # 图例系列名“苹果”,颜色#696969
41 | # 图例系列名“小米“,颜色#3cb371
42 | # 图例系列名“三星”,颜色#ff8c00
43 | # 8. 保存图片
44 | # 保存路径
45 | resultPath = "./result"
46 | if not os.path.exists(path=resultPath):
47 | os.mkdir(path=resultPath)
48 | # 保存文件名
49 | resultFileName = "phone_display_radar.html"
50 |
51 | # 准备坐标轴
52 | c_schema = [
53 | opts.RadarIndicatorItem(name="外观", max_=10),
54 | opts.RadarIndicatorItem(name="性能", max_=10),
55 | opts.RadarIndicatorItem(name="拍照", max_=10),
56 | opts.RadarIndicatorItem(name="系统", max_=10),
57 | opts.RadarIndicatorItem(name="屏幕", max_=10)
58 | ]
59 | # 执行绘图
60 | radar = (
61 | Radar(init_opts=opts.InitOpts(theme="chalk"))
62 | .set_global_opts(
63 | title_opts=opts.TitleOpts(title="Amy专业手机评测"),
64 | legend_opts=opts.LegendOpts(
65 | orient="vertical",
66 | pos_left="10%",
67 | pos_bottom="50%"
68 | )
69 | )
70 | .add_schema(
71 | schema=c_schema,
72 | splitarea_opt=opts.SplitAreaOpts(
73 | is_show=True,
74 | areastyle_opts=opts.AreaStyleOpts(opacity=1)
75 | ),
76 | shape="circle"
77 | )
78 | .add(
79 | data=[orgData[0][1:6]],
80 | series_name=orgData[0][0],
81 | color="#800080",
82 | label_opts=opts.LabelOpts(is_show=False),
83 | areastyle_opts=opts.AreaStyleOpts(opacity=0.1)
84 | )
85 | .add(
86 | data=[orgData[1][1:6]],
87 | series_name=orgData[1][0],
88 | color="#6495ed",
89 | label_opts=opts.LabelOpts(is_show=False),
90 | areastyle_opts=opts.AreaStyleOpts(opacity=0.1)
91 | )
92 | .add(
93 | data=[orgData[2][1:6]],
94 | series_name=orgData[2][0],
95 | color="#696969",
96 | label_opts=opts.LabelOpts(is_show=False),
97 | areastyle_opts=opts.AreaStyleOpts(opacity=0.1)
98 | )
99 | .add(
100 | data=[orgData[3][1:6]],
101 | series_name=orgData[3][0],
102 | color="#3cb371",
103 | label_opts=opts.LabelOpts(is_show=False),
104 | areastyle_opts=opts.AreaStyleOpts(opacity=0.1)
105 | )
106 | .add(
107 | data=[orgData[4][1:6]],
108 | series_name=orgData[4][0],
109 | color="#ff8c00",
110 | label_opts=opts.LabelOpts(is_show=False),
111 | areastyle_opts=opts.AreaStyleOpts(opacity=0.1)
112 | )
113 | .render(path=os.path.join(resultPath, resultFileName))
114 | )
115 |
--------------------------------------------------------------------------------
/15综合评估之雷达图/example15_3/resources/test.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/15综合评估之雷达图/example15_3/resources/test.xlsx
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_1/example16_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Geo
3 | import pyecharts.options as opts
4 | from pyecharts.globals import GeoType
5 |
6 | # 地理坐标图表达某人旅游去往某一城市的意向
7 |
8 | # 构造原始数据对(省略读表的过程):10个城市和对应的期望值
9 |
10 | data = [('台湾', '10'), ('西安', '30'), ('重庆', '80'), ('香港', '20'), ('广州', '100'),
11 | ('武汉', '90'), ('长沙', '40'), ('北京', '50'), ('上海', '70'), ('成都', '100')]
12 |
13 | # 绘图需求
14 | # 1. 地图坐标系(schema)为中国地图
15 | # 2. 图例系列名称为空,数据标签隐藏
16 | # 3. 地理坐标图的类型设置为在其上打散点(scatter)
17 | # 4. 加视觉映射
18 | # 5. 保存
19 | # 保存路径
20 | resultPath = "./result"
21 | if not os.path.exists(path=resultPath):
22 | os.mkdir(path=resultPath)
23 | # 保存文件名
24 | resultFileName = "travel_geo.html"
25 | # 执行绘图
26 | geo = (
27 | Geo()
28 | .set_global_opts(visualmap_opts=opts.VisualMapOpts(is_show=True))
29 | .add_schema(maptype="china")
30 | .add(
31 | series_name="",
32 | data_pair=data,
33 | label_opts=opts.LabelOpts(is_show=False),
34 | type_=GeoType.SCATTER # 或者直接"scatter"
35 | )
36 | .render(path=os.path.join(resultPath, resultFileName))
37 | )
38 |
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_2/example16_2.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Geo, Timeline
3 | import pyecharts.options as opts
4 | import openpyxl
5 | from openpyxl.worksheet.worksheet import Worksheet
6 | from openpyxl.workbook.workbook import Workbook
7 | from pyecharts.globals import GeoType
8 |
9 | # 使用地理坐标图+轮播图,描绘今年来全国气温的变化
10 |
11 | # 配置文件
12 | # 资源文件目录
13 | resourcesPath = "./resources"
14 | # 近年来的温度文件
15 | temperatureBookName = "全国十年年平均温度.xlsx"
16 | # 年平均气温工作表
17 | temperatureSheetName = "年平均气温"
18 |
19 | # 打开文件,选表
20 | temperatureSheet = openpyxl.load_workbook(
21 | filename=os.path.join(resourcesPath, temperatureBookName)
22 | )[temperatureSheetName] # type: Worksheet
23 |
24 | # 取出所有的原始数据
25 | orgData = [list(row_item) for row_item in temperatureSheet.iter_cols(values_only=True)]
26 | # print(orgData)
27 |
28 | # 清洗取值为None的列
29 | # 去掉末尾附加None值,注意,orgData[:]另外深拷贝一个副本,原列表
30 | for row_item in orgData[:]:
31 | if None in row_item:
32 | orgData.remove(row_item)
33 | # print(orgData)
34 |
35 | # 第一行的列表,去掉”城市”这个字,多余
36 | orgData[0] = orgData[0][1:]
37 | # print(orgData)
38 |
39 |
40 | # 组装可视化需要的数据
41 | def get_data(col_num) -> tuple:
42 | """
43 | 用于绘制一张轮播图需要的数据(第i列,i始于1)
44 | :param col_num:
45 | :return: (年份,[绘图所需数据对])
46 | """
47 | # 从原始数据中,提取年份和各个城市需要的数据
48 | year_, city_data = orgData[col_num][0], orgData[col_num][1:]
49 | # 组装城市-数据对
50 | data_pair = zip(orgData[0], city_data)
51 | # 返回(年份,[绘图所需数据对])
52 | return year_, list(data_pair)
53 |
54 |
55 | # 地理坐标图绘图需求
56 | # 1. 地图坐标类型选择中国地图,用热力图方式体现温度
57 | # 2. 图例为空
58 | # 3. 设置视觉配置项,但隐藏,最大映射值为25,分段型映射(怎么设置可以查查官方文档)
59 | # 4. 轮播节点名为“xxx年”
60 | # 5. 每个图的名字设置为“xxx年全国主要城市平均温度”
61 | # 6. 保存
62 | # 保存路径
63 | resultPath = "./result"
64 | if not os.path.exists(path=resultPath):
65 | os.mkdir(path=resultPath)
66 | # 保存文件名
67 | resultFileName = "TEMP_geo_timeline.html"
68 | # 执行绘图
69 | # 轮播图框架
70 | timeline = Timeline()
71 | # 一个个往里加轮播图
72 | for colNum in range(1, len(orgData)):
73 | year, dataPair = get_data(col_num=colNum)
74 | # print(year, dataPair)
75 | # 添加新的地理坐标图
76 | timeline.add(
77 | time_point=f"{year}年",
78 | chart=(
79 | Geo()
80 | .set_global_opts(
81 | title_opts=opts.TitleOpts(title=f"{year}年全国主要城市平均温度"),
82 | visualmap_opts=opts.VisualMapOpts(
83 | is_show=False,
84 | max_=25,
85 | is_piecewise=True
86 | )
87 | )
88 | .add_schema(maptype="china")
89 | .add(
90 | series_name="",
91 | type_=GeoType.HEATMAP,
92 | data_pair=dataPair,
93 | )
94 | )
95 | )
96 | # 执行保存
97 | timeline.render(path=os.path.join(resultPath, resultFileName))
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_2/resources/全国十年年平均温度.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/16地理描述之地理坐标图/example16_2/resources/全国十年年平均温度.xlsx
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_3/example16_3.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Geo
3 | from pyecharts.globals import GeoType, ThemeType
4 | import pyecharts.options as opts
5 | import openpyxl
6 | from openpyxl.worksheet.worksheet import Worksheet
7 | from openpyxl.workbook.workbook import Workbook
8 |
9 | # 用地理坐标图,描述成都一家网店寄往其他地区商品的邮费情况
10 |
11 | # 资源文件
12 | resourcesPath = "./resources"
13 | # 全国运输文件
14 | transBookName = "全国运输.xlsx"
15 | # 全国邮费工作表
16 | transSheetName = "全国邮费"
17 | # 开文件、选表
18 | transBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, transBookName)) # type: Workbook
19 | transSheet = transBook[transSheetName] # type: Worksheet
20 |
21 | # 读取所有原始数据(跳过表头)
22 | # 列含义:[起点, 终点, 邮费]
23 | orgData = [list(row_item) for row_item in transSheet.iter_cols(min_row=2, min_col=1, values_only=True)]
24 | # print(orgData)
25 |
26 | # 清洗数据None,[:]深拷贝,防止下标错位
27 | for rowItem in orgData[:]:
28 | for cellItem in rowItem[:]:
29 | if cellItem is None:
30 | rowItem.remove(cellItem)
31 | if len(rowItem) == 0:
32 | orgData.remove(rowItem)
33 | # print(orgData)
34 |
35 | # 按照[起点, 终点]的方式添加两地的边;按照[终点, 到终点的邮费]这种方式构造目的地的带权节点
36 | # 边数据对的构造
37 | routeList = zip(orgData[0], orgData[1])
38 | # 带权节点的构造
39 | postageList = zip(orgData[1], orgData[2])
40 |
41 | # 绘制地理坐标图的需求
42 | # 1. 坐标类型是中国地图
43 | # 2. 同时添加带权节点和边两类坐标图要素,带权节点为动态散点样式,边为流向样式(类型设置可以参照文档)
44 | # 3. 图例系列均设为空,隐藏数据标签
45 | # 4. 图的主题为dark
46 | # 5. 添加最大映射为10,最小映射为4
47 | # 6. 保存
48 | # 保存路径
49 | resultPath = "./result"
50 | if not os.path.exists(path=resultPath):
51 | os.mkdir(path=resultPath)
52 | # 保存文件名
53 | resultFileName = "postage_geo.html"
54 | # 执行绘图
55 | geo = (
56 | Geo(init_opts=opts.InitOpts(theme=ThemeType.DARK))
57 | .set_global_opts(visualmap_opts=opts.VisualMapOpts(min_=4, max_=10))
58 | .add_schema(maptype="china")
59 | .add(
60 | series_name="",
61 | data_pair=postageList,
62 | type_=GeoType.EFFECT_SCATTER,
63 | label_opts=opts.LabelOpts(is_show=False)
64 | )
65 | .add(
66 | series_name="",
67 | data_pair=routeList,
68 | type_=GeoType.LINES,
69 | label_opts=opts.LabelOpts(is_show=False)
70 | )
71 | .render(path=os.path.join(resultPath, resultFileName))
72 | )
73 |
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_3/resources/全国运输.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/16地理描述之地理坐标图/example16_3/resources/全国运输.xlsx
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_4/example16_4.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Geo
3 | from pyecharts.globals import GeoType
4 | import pyecharts.options as opts
5 |
6 | # 使用地理坐标图,表达自己一年来的出差情况
7 |
8 | # 准备原始数据,省略读取文档的过程
9 | # 出差去往各点的次数:带权节点(地点, 出差次数)
10 | businessTimes = [("北京", 50), ("广州", 30), ("成都", 40), ("哈尔滨", 10)]
11 | # 每次出差的路线图:边(起点, 终点)
12 | businessFlow = [("上海", "广州"), ("上海", "哈尔滨"), ("上海", "北京"), ("上海", "成都"), ("北京", "成都"), ("哈尔滨", "广州")]
13 |
14 | # 绘制地理坐标图需求
15 | # 1. 坐标轴设置:选择中国地图
16 | # 2. 带权节点设置:图例系列名为空,设置为动态散点显示,隐藏数据标签
17 | # 3. 边的设置:图例名称为空,设置为流向显示,隐藏数据标签;美化涟漪特效(查文档说明):箭头大小为5,黄色,弯曲度20%
18 | # 4. 视觉映射:最大和最小设置分别为60和10
19 | # 5. 标题为“出差大盘点”
20 | # 6. 保存
21 | # 保存路径
22 | resultPath = "./result"
23 | if not os.path.exists(path=resultPath):
24 | os.mkdir(path=resultPath)
25 | # 保存文件名
26 | resultFileName = "on_business_geo.html"
27 | # 执行绘图
28 | geo = (
29 | Geo()
30 | .set_global_opts(
31 | title_opts=opts.TitleOpts(title="出差大盘点"),
32 | visualmap_opts=opts.VisualMapOpts(max_=60, min_=10)
33 | )
34 | .add_schema(maptype="china")
35 | .add(
36 | # 带权节点
37 | series_name="",
38 | type_=GeoType.EFFECT_SCATTER,
39 | data_pair=businessTimes,
40 | label_opts=opts.LabelOpts(is_show=False)
41 | )
42 | .add(
43 | # 边
44 | series_name="",
45 | type_=GeoType.LINES,
46 | data_pair=businessFlow,
47 | effect_opts=opts.EffectOpts(
48 | symbol="arrow",
49 | symbol_size=5,
50 | color="yellow"
51 | ),
52 | linestyle_opts=opts.LineStyleOpts(
53 | curve=0.2
54 | ),
55 | label_opts=opts.LabelOpts(is_show=False)
56 | )
57 | .render(path=os.path.join(resultPath, resultFileName))
58 | )
59 |
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_5/example16_5.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Geo
3 | import pyecharts.options as opts
4 | from pyecharts.globals import GeoType
5 | import openpyxl
6 | from openpyxl.workbook.workbook import Workbook
7 | from openpyxl.worksheet.worksheet import Worksheet
8 |
9 | # 使用地理坐标图,表达某产品在全国范围的用户分布
10 |
11 | # 资源文件夹
12 | resourcesPath = "./resources"
13 | # 用户分布文件
14 | userBookName = "用户分布.xlsx"
15 | # 用户分布工作表
16 | userSheetName = "用户数量"
17 |
18 | # 打开文件并选表
19 | userSheet = openpyxl.load_workbook(
20 | filename=os.path.join(resourcesPath, userBookName))[userSheetName] # type: Worksheet
21 | # 取出数据对
22 | num_list = [row_item for row_item in userSheet.iter_rows(min_row=2, values_only=True)]
23 | print(num_list)
24 |
25 | # 绘制地理坐标图需求
26 | # 1. 添加但隐藏视觉映射,最大映射1000,过渡颜色设置为['#33bbff','#0015ff','#2600e5','#8a2ee5','#cc2996']
27 | # 2. 全图背景颜色为#475262
28 | # 3. 坐标系设置:中国地图,地图底色为#2d3948,描边为#2efef7;鼠标选中高亮情况下,颜色为#2a333d
29 | # 4. 设置散点样式表达单一地点的用户分布情况,设置热力图表达单一地点及附近地区的用户分布情况,均隐藏数据标签,图例系列名不用填
30 | # 5. 图的标题:会员分布
31 | # 6. 保存
32 | # 保存路径
33 | resultPath = "./result"
34 | if not os.path.exists(path=resultPath):
35 | os.mkdir(path=resultPath)
36 | # 保存文件名
37 | resultFileName = "user_geo.html"
38 | # 执行地理坐标图绘制
39 | geo = (
40 | Geo(init_opts=opts.InitOpts(bg_color="#475262"))
41 | .set_global_opts(
42 | title_opts=opts.TitleOpts(title="会员分布"),
43 | visualmap_opts=opts.VisualMapOpts(
44 | is_show=False,
45 | max_=1000,
46 | range_color=["#33bbff", "#0015ff", "#2600e5", "#8a2ee5", "#cc2996"]
47 | )
48 | )
49 | .add_schema(
50 | maptype="china",
51 | itemstyle_opts=opts.ItemStyleOpts(color="#2d3948", border_color="#2efef7"),
52 | emphasis_itemstyle_opts=opts.ItemStyleOpts(color="#2a333d")
53 | )
54 | .add(
55 | # 单区域散点表达
56 | series_name="",
57 | data_pair=num_list,
58 | type_=GeoType.SCATTER,
59 | label_opts=opts.LabelOpts(is_show=False)
60 | )
61 | .add(
62 | # 区域热力图表达
63 | series_name="",
64 | data_pair=num_list,
65 | type_=GeoType.HEATMAP,
66 | label_opts=opts.LabelOpts(is_show=False)
67 | )
68 | .render(path=os.path.join(resultPath, resultFileName))
69 | )
70 |
--------------------------------------------------------------------------------
/16地理描述之地理坐标图/example16_5/resources/用户分布.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/16地理描述之地理坐标图/example16_5/resources/用户分布.xlsx
--------------------------------------------------------------------------------
/17多对多映射联系之关系图/example17_1/example17_1.py:
--------------------------------------------------------------------------------
1 | import os
2 | from pyecharts.charts import Graph
3 | import pyecharts.options as opts
4 | from pyecharts.commons.utils import JsCode
5 | import openpyxl
6 | from openpyxl.workbook.workbook import Workbook
7 | from openpyxl.worksheet.worksheet import Worksheet
8 |
9 | # 使用关系图,可视化Python知识点关联图谱
10 |
11 | # 资源文件夹
12 | resourcesPath = "./resources"
13 | # 知识点文件
14 | knowledgeBookName = "知识点.xlsx"
15 | # 存储边的父子节点所在工作表
16 | linkSheetName = "知识点的关系"
17 | # 存储各个知识点带权节点的(节点名, 权重)关系
18 | nodeSheetName = "数量统计"
19 |
20 | # 打开文件
21 | knowledgeBook = openpyxl.load_workbook(filename=os.path.join(resourcesPath, knowledgeBookName)) # type: Workbook
22 | # 边工作表
23 | linkSheet = knowledgeBook[linkSheetName] # type: Worksheet
24 | # 节点工作表
25 | nodeSheet = knowledgeBook[nodeSheetName] # type: Worksheet
26 |
27 | # 读取表格清洗后的数据(通常这个表格数据是清洗后的,得到这个表格前可能需要清洗自然语言)
28 | # (知识点, 知识点)组成的边
29 | orgLinkList = [rowItem for rowItem in linkSheet.iter_rows(min_row=2, values_only=True)]
30 | # (知识点, 权重)组成的节点
31 | orgNodeList = [rowItem for rowItem in nodeSheet.iter_rows(min_row=2, values_only=True)]
32 | print(orgLinkList)
33 | print(orgNodeList)
34 |
35 | # 按[{"source": xxx, "target": xxx}, ...]格式组合边的数据
36 | # 原始数据转化为指定格式方法
37 | linkList = [opts.GraphLink(source=linkItem[0], target=linkItem[1]) for linkItem in orgLinkList]
38 | # 按[{"id":"Python", "name":"Python ", "symbolSize":24}]格式组合节点数据,且假设id就是节点名(这里没有重名)
39 | # 注意:这里节点的id是自定义添加的字段,用作唯一标识
40 | # nodeList = [opts.GraphNode(id=nodeItem[0], name=nodeItem[0], symbol_size=nodeItem[1]) for nodeItem in orgNodeList]
41 | nodeList = [{"id": nodeItem[0], "name": nodeItem[0], "symbolSize": nodeItem[1]} for nodeItem in orgNodeList]
42 |
43 | # 绘制关系图需求:
44 | # 1. 设置图表的图例系列名称为空;
45 | # 2. 整体呈圆形布局,数据标签可依照节点实际情况进行旋转调整
46 | # 3. 用给定的js代码设置边为渐变色(怎么设置可以查文档)
47 | # 4. 边的弯曲度设为0.3,宽度设为1.5;
48 | # 5. 节点的颜色"#474747";
49 | # 6. 标题设置为:Python知识图谱;
50 | # 7. 保存图表
51 | # 保存路径
52 | resultPath = "./result"
53 | if not os.path.exists(path=resultPath):
54 | os.mkdir(path=resultPath)
55 | # 保存文件名
56 | resultFileName = "pythonKG_graph.html"
57 |
58 | # 用于控制边渐变颜色的js代码(具体参数含义官方文档中有给出说明)
59 | line_color_js = """
60 | new echarts.graphic.LinearGradient(
61 | 0,0,0,1,
62 | [{offset: 0,
63 | color: '#2e9afe'},
64 | {
65 | offset: 0.3,
66 | color: '#01a9db'},
67 | {
68 | offset: 0.6,
69 | color: '#f5bca9'},
70 | {
71 | offset: 1,
72 | color: '#b40404'}]
73 | )
74 | """
75 |
76 | # 执行绘图
77 | knowledgeGraph = (
78 | Graph()
79 | .set_global_opts(title_opts=opts.TitleOpts(title="Python知识图谱"))
80 | .add(
81 | series_name="",
82 | links=linkList,
83 | nodes=nodeList,
84 | layout="circular",
85 | is_rotate_label=True,
86 | linestyle_opts=opts.LineStyleOpts(
87 | color=JsCode(js_code=line_color_js),
88 | curve=0.3,
89 | width=1.5
90 | ),
91 | itemstyle_opts=opts.ItemStyleOpts(color="#474747")
92 | )
93 | .render(path=os.path.join(resultPath, resultFileName))
94 | )
95 |
--------------------------------------------------------------------------------
/17多对多映射联系之关系图/example17_1/resources/知识点.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cutelittletiantian/python-data-visualization/360c5e967be007891792e1627910959d561e1207/17多对多映射联系之关系图/example17_1/resources/知识点.xlsx
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Michael Du
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 前排提示
2 |
3 | 内容有在续建设中,请持续关注,爱你们哟ღ( ´・ᴗ・` )。
4 |
5 | # 简介
6 |
7 | 近期工作压力巨大,常年在地铁上刷着干瘪的短视频和段子,我看到了**世界的参差**\_(:з」∠)\_,对于美的追求的精神世界无比枯竭。直到有一天,我看到了,在一些学术论文中,出现了许多美丽的图片(如反映多维数据分布及相关性的**散点图和气泡图**、表现流量分布的**桑基图**等),这些图片的美感在于,它们将冰冷的数据用生动的图像演绎出来,无比炫酷,给人以无限的遐想和学习的兴趣。
8 |
9 | 想想马上就要读研究生的我,也许多年后需要自己生成~~美丽的~~图像,为了多年后别把自己~~精心研究的数据~~(当然也可能是脚踩的数据)绘图成跟shi一样,更重要的是**为了在感受世界的参差时静下心来,享受学术的美丽、数据的美丽**,我决定入坑学习Python数据可视化,并把学习成果与大家交流共享。
10 |
11 | 持续建设中,大家可以关注,平日里要打工,不定期更新(提前为自己的咕咕咕找好借口)
12 |
13 | # 配置要求
14 |
15 | > OS: ``Windows 10``或者``MacOS``均可(注意:``Windows 10``或者``MacOS``仅在某些方面,比如文件路径的表示上可能略有不同)
16 | >
17 | > Python版本: 本项目采用``3.9.x 64-bit``版本(截至2021年4月26日查询Python官网``https://www.python.org``,Python最新版本为3.9.x)
18 | >
19 | > 推荐的编辑器:``Pycharm``或``Jupyter``,看你喜好啦~推荐使用虚拟环境(venv),在为本项目进行必要的第三方库配置时,不影响其它Python项目的配置,不污染系统Python的环境。
20 |
21 | # 需要用到的Python库
22 |
23 | ``pyecharts``:本项目**最主要的**第三方库之一,打开cmd(或其它操作系统的终端),使用``pip install pyecharts``进行安装。
24 |
25 | > 用途:将数据进行可视化,生成各种可交互式的图表。
26 | >
27 | > 导入方式:直接采用``import pyecharts``导入有其不足点,通常我们这样导入pyecharts包
28 |
29 | ```python
30 | # 导入options模块并简写为opts
31 | import pyecharts.options as opts
32 | # 从pyecharts.charts中导入“某一特定类型图”(some-package)模块
33 | from pyecharts.charts import
34 | ```
35 |
36 | 其中上述````,根据需要绘制的图形类型进行特别指定,画柱状图就换成``Bar``,画线状图就指定``Line``,画桑基图就指定``Sankey``等。
37 |
38 | 举例:假如要绘制柱状图(Bar chart),就这样导入``pyecharts``库
39 |
40 | ```python
41 | # 导入options模块并简写为opts
42 | import pyecharts.options as opts
43 | # 从pyecharts.charts中导入 Bar 模块
44 | from pyecharts.charts import Bar
45 | ```
46 |
47 | ***
48 |
49 | ``openpyxl``:第三方库,打开cmd(或其它操作系统的终端),使用``pip install openpyxl``进行安装。
50 |
51 | > 用途:对excel表格进行读写操作。
52 | >
53 | > 导入方式:原则上采用``import openpyxl``便足以满足开发需要,但是为了尽可能发挥代码提示的功能,推荐如下方式导入
54 |
55 | ```python
56 | import openpyxl # 最主要的导入
57 | from openpyxl.utils import cell
58 | from openpyxl import Workbook # 这个导入和type注释会共同起作用
59 | from openpyxl.worksheet.worksheet import Worksheet # 这个导入和type注释会共同起作用
60 | ```
61 |
62 | 另注:为了显示代码提示,建议在对工作簿、工作表变量赋值后,用注释在同一行指明类型(格式:``# type: 类型名``),例如
63 |
64 | ```python
65 | import openpyxl # 最主要的导入
66 | from openpyxl.utils import cell
67 | from openpyxl import Workbook # 这个导入和type注释会共同起作用
68 | from openpyxl.worksheet.worksheet import Worksheet # 这个导入和type注释会共同起作用
69 |
70 | workBook = openpyxl.load_workbook(filename=recordPath) # type: Workbook
71 | workSheet = photoParamBook["示例"] # type: Worksheet
72 | ```
73 |
74 | ***
75 |
76 | ### 安装第三方包出错的解决方法
77 |
78 | 有时安装失败是因为国内网络有一些限制,这时您可以尝试使用清华大学镜像下载相应的包,即``pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package``,其中``some-package``换成自己所需要安装的第三方库名。
79 |
80 | > 注意:使用镜像前请确保自己的pip处于较新版本(>=10.0.0)
81 | >
82 | > 更新pip使用命令:``python -m pip install --upgrade pip``
83 |
84 | ***
85 |
86 | # 请注意
87 |
88 | * 当您在运行Python的样例时,请预先安装好所需的第三方库依赖,**并关闭resources目录中所涉及的文件**(如果有),以免因为文件占用导致程序不能处理打开着的文件。
89 | * 使用库的时候,不要死记硬背,常见的思路记住即可,细节的东西可以随机应变或者查官方文档进行处理。
90 | * 导入第三方库时,部分第三方库(例如``openpyxl``)的类单独导入进来,结合形如``# type: ...``格式的注释,有利于充分利用好编辑器的代码填充提示,使第三方库的封装更有意义。
91 |
92 | # 快捷传送门
93 |
94 | 本项目中,所涉及库等内容的文档链接如下。
95 |
96 | ``Python``官网及其官方文档
97 |
98 | > 官网:https://www.python.org
99 | >
100 | > 文档:https://docs.python.org/3/
101 |
102 | 本项目**最主要的**第三方库之一``pyecharts``官方文档
103 |
104 | > https://pyecharts.org/
105 |
106 | ``openpyxl``第三方库官方文档
107 |
108 | > https://openpyxl.readthedocs.io/en/stable/index.html
109 |
110 | 清华大学开源软件镜像站(当第三方库无法直接下载时,可以考虑镜像站)
111 |
112 | > 网址:[清华大学开源软件镜像站 | Tsinghua Open Source Mirror](https://mirrors.tuna.tsinghua.edu.cn/)
113 | >
114 | > 使用镜像安装第三方库格式:``pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package``
115 | >
116 | > (请将上述``some-package``换成自己需要的第三方库名,例如``pyecharts``)
117 | >
118 | > 注意:使用镜像前请确保自己的pip处于较新版本(>=10.0.0)
119 | >
120 | > 更新pip使用命令:``python -m pip install --upgrade pip``
121 |
122 | # 小添添的其它Python坑
123 |
124 | **Python自动化办公**:使用``os`` ``openpyxl`` ``python-docx`` ``pdfplumber``等第三方库批量分类文件、批量读写Excel文档、批量读写Word文档、批量获取文字类Pdf文档、基于SMTP和MIME协议的邮件批量发送内容等,通过一些典型的应用场景,大幅提升职场办公室工作效率。
125 |
126 | > 传送门:https://github.com/cutelittletiantian/python-for-office
127 |
--------------------------------------------------------------------------------
/综合应用:制作可视化大屏/可视化大屏demo/result/config/page_screen_config.json:
--------------------------------------------------------------------------------
1 | [{"cid":"77d3dfacc1ac4d2ebcb0072684a646f7","width":"787px","height":"408px","top":"41px","left":"8px"},{"cid":"61396965445041279331cfabc8eb57e8","width":"907px","height":"500px","top":"449px","left":"8px"},{"cid":"8942f571ea0d46c5a6579c46051d492f","width":"536px","height":"408px","top":"41px","left":"795px"},{"cid":"b21b2e3c5d89498db499337ec9935f22","width":"906px","height":"501px","top":"949px","left":"8px"},{"cid":"7ecdd15281234448ae4106fc5675d2d8","width":"683px","height":"408px","top":"41px","left":"1330px"},{"cid":"74c9da272ad441139c9f7c31f56ed405","width":"414px","height":"500px","top":"449px","left":"915px"},{"cid":"996ff074453249b8b1ee89d126cfd1d1","width":"684px","height":"500px","top":"449px","left":"1329px"},{"cid":"8b235cbdbe5743589ce70b765226c52d","width":"1099px","height":"501px","top":"949px","left":"914px"}]
--------------------------------------------------------------------------------