- 总结
- 可视化知识
- Matplotlib
- turtle
- streamlit
- seaborn
- pyecharts
- smartchart
- PyGraphviz
- turtle工具
- 动画
- 结束
总结
- 可视化方法
- 【2020-8-7】Python数据可视化工具测评:5大工具谁是第一?
- Matplotlib、Pyecharts、Seaborn、Plotly、Bokeh这五大工具
- 评测维度
- Seaborn和Plotly、bokeh有一个共同的地方就是虽然强大,但是网上有关这三个库的教程、讨论都远少于Pyecharts与Matplotlib
工具 | 得分 | 分布 | 示例 |
---|---|---|---|
Pyecharts | 85 | ||
Matplotlib | 77 | ||
Plotly | 76 | ||
Bokeh | 71 | ||
Seaborn | 72 |
可视化知识
什么场景用什么图
- 【2021-11-11】数据分析最有用的25个 Matplotlib图, 本文参考自原文,包含以下各种图形的源码及示例
1.关联
- 散点图
- Scatteplot是用于研究两个变量之间关系的经典和基本图。如果数据中有多个组,则可能需要以不同颜色可视化每个组。在Matplotlib,你可以方便地使用。
- 带边界的气泡图
- 在边界内显示一组点以强调其重要性。在此示例中,从应该被环绕的数据帧中获取记录,并将其传递给下面的代码中描述的记录。encircle()
- 带线性回归最佳拟合线的散点图
- 了解两个变量如何相互改变
- 抖动图
- 通常多个数据点具有完全相同的X和Y值。结果多个点相互绘制并隐藏。为避免这种情况,请稍微抖动点,以便您可以直观地看到它们
- 计数图
- 避免点重叠问题的另一个选择是增加点的大小,这取决于该点中有多少点。因此,点的大小越大,周围的点的集中度就越大。
- 边缘直方图
- 边缘直方图具有沿X和Y轴变量的直方图。这用于可视化X和Y之间的关系以及单独的X和Y的单变量分布。该图如果经常用于探索性数据分析(EDA)
- 边缘箱形图
- 边缘箱图与边缘直方图具有相似的用途。然而,箱线图有助于精确定位X和Y的中位数,第25和第75百分位数。
- 相关图
- Correlogram用于直观地查看给定数据帧(或2D数组)中所有可能的数值变量对之间的相关度量。
# Import Dataset
df = pd.read_csv("https://github.com/selva86/datasets/raw/master/mtcars.csv")
# Plot
plt.figure(figsize=(12,10), dpi= 80)
sns.heatmap(df.corr(), xticklabels=df.corr().columns, yticklabels=df.corr().columns, cmap='RdYlGn', center=0, annot=True)
# Decorations
plt.title('Correlogram of mtcars', fontsize=22)
plt.xticks(fontsize=12)
plt.yticks(fontsize=12)
plt.show()
- 矩阵图
- 成对图是探索性分析中的最爱,以理解所有可能的数字变量对之间的关系。它是双变量分析的必备工具。
# Load Dataset
df = sns.load_dataset('iris')
# Plot
plt.figure(figsize=(10,8), dpi= 80)
sns.pairplot(df, kind="scatter", hue="species", plot_kws=dict(s=80, edgecolor="white", linewidth=2.5))
plt.show()
2.偏差
- 发散型条形图
- 想根据单个指标查看项目的变化情况,并可视化此差异的顺序和数量,那么发散条是一个很好的工具。它有助于快速区分数据中组的性能,并且非常直观,并且可以立即传达这一点。
- 发散型文本
- 分散的文本类似于发散条,如果你想以一种漂亮和可呈现的方式显示图表中每个项目的价值
- 发散型包点图
- 发散点图也类似于发散条。然而,与发散条相比,条的不存在减少了组之间的对比度和差异。
- 带标记的发散型棒棒糖图
- 面积图
3.排序
- 有序条形图
- 棒棒糖图
- 包点图
- 坡度图
- 斜率图最适合比较给定人/项目的“之前”和“之后”位置。
- 哑铃图
4.分布
- 连续变量的直方图
- 直方图显示给定变量的频率分布。下面的表示基于分类变量对频率条进行分组,从而更好地了解连续变量和串联变量
- 类型变量的直方图
- 分类变量的直方图显示该变量的频率分布。通过对条形图进行着色,您可以将分布与表示颜色的另一个分类变量相关联。
- 密度图
- 密度图是一种常用工具,可视化连续变量的分布。通过“响应”变量对它们进行分组,您可以检查X和Y之间的关系。以下情况,如果出于代表性目的来描述城市里程的分布如何随着汽缸数的变化而变化。
- 直方密度线图
- 带有直方图的密度曲线将两个图表传达的集体信息汇集在一起,这样您就可以将它们放在一个图形而不是两个图形中
- Joy Plot
- Joy Plot允许不同组的密度曲线重叠,这是一种可视化相对于彼此的大量组的分布的好方法。它看起来很悦目,并清楚地传达了正确的信息。它可以使用joypy基于的包来轻松构建matplotlib。
- 分布式包点图
- 包点+箱形图
- Dot + Box Plot
- 小提琴图
- 人口金字塔
- 分类图
5.组成
- 华夫饼图
- 饼图
- 树形图
- 条形图
6.变化
- 时间序列图
- 带波峰波谷标记的时序图
- 自相关和部分自相关图
- 交叉相关图
- 时间序列分解图
- 多个时间序列
- 使用辅助Y轴来绘制不同范围的图形
- 带有误差带的时间序列
- 堆积面积图
- 未堆积的面积图
- 日历热力图
- 季节图
7.分组
- 树状图
- 簇状图
- 安德鲁斯曲线
- 平行坐标
可视化工具
方案有如下可选型:
- 一、传统的matplotlibicon,seaborn,绘制的是静态图。
- 二、pyecharts,plotly,使用纯python代码,但生成的是htmlicon,可以缩放之类的。
- 三、bokeh,plotly+dash,交互式的,有相应的控件。也是使用python的方式,生成html。
- 四、streamlit。
- dataprep:一次性EDA工具
自动生成分析报告
【2022-1-25】5个方便好用的Python自动化脚本
可视化一般会用pandas、matplotlib等工具来探索数据,但需要自己编写大量代码,如果想提高效率,Dtale是个不错的选择。
- Dtale特点是用一行代码生成自动化分析报告,它结合了Flask后端和React前端,提供了一种查看和分析Pandas数据结构的简便方法。
- 可以在Jupyter上实用Dtale。
需要的第三方库:
- Dtale - 自动生成分析报告
### Importing Seaborn Library For Some Datasets
import seaborn as sns
### Printing Inbuilt Datasets of Seaborn Library
print(sns.get_dataset_names())
### Loading Titanic Dataset
df=sns.load_dataset('titanic')
### Importing The Library
import dtale
#### Generating Quick Summary
dtale.show(df)
效果:
Notebook
dataprep
dataprep EDA 工具,直接展示 各个属性取值、相关性、热力图等信息
安装 dataprep 工具包
pip install -U dataprep
以官方数据集为例,做EDA分析
from dataprep.datasets import load_dataset
from dataprep.eda import create_report
from dataprep.eda import plot, plot_correlation, plot_missing
# 内置数据集信息
from dataprep.datasets import get_dataset_names
get_dataset_names()
# ['covid19',
# 'wine-quality-red',
# 'iris',
# 'waste_hauler',
# 'countries',
# 'patient_info',
# 'house_prices_train',
# 'adult',
# 'house_prices_test',
# 'titanic']
# 加载内置数据集
df = load_dataset("adult") #
df = load_dataset("titanic") # 泰坦尼克数据集
# 属性取值分析
from dataprep.eda import plot
plot(df) # 所有属性取值分布(柱状图)
plot(df, 'queryChanging') # 单个属性取值分布,额外新增饼图、词云、词长
# 相关性分析: 显示3种相关性结果
from dataprep.eda import plot_correlation
plot_correlation(df)
# 计算相关性, 输出到文件
from dataprep.eda import compute_correlation
from dataprep.datasets import load_dataset
df = load_dataset("titanic")
imdt = compute_correlation(df)
imdt.save("imdt.json")
imdt
# 缺失值分析
from dataprep.eda import plot_missing
plot_missing(df)
# 多数据集对比分析: 各数据集格式相同
from dataprep.eda import plot_diff
from dataprep.datasets import load_dataset
df1 = load_dataset("house_prices_test")
df2 = load_dataset("house_prices_train")
plot_diff([df1, df2])
# 创建报表: 汇总分析结果,点击单个属性的详情(detail)就会出现各种类型的图表
r = create_report(df)
r = create_report(df, title='泰坦尼克分析报告')
r # 在 notebook 中展示
r.show_browser() # 浏览器页面
r.save(filename='report', to='~/Desktop') # 保存为本地文件
# 部分显示
plot(df) # 变量可视化
plot_correlation(df) # 不同类型相关图
# ---- 定制报表 -----
from dataprep.eda import plot,create_report
from dataprep.datasets import load_dataset
df = load_dataset('titanic')
# 显示指定tab页: display 参数
plot(df, 'Pclass', display=['Stats', 'Bar Chart', 'Pie Chart'])
plot(df, display=["Stats", "Insights"])
# 指定tab页
create_report(df,display=["Overview","Interactions"])
# 定制图标属性: config 参数
plot(df, "Pclass", config={'bar.bars': 10, 'bar.sort_descending': True, 'bar.yscale': 'linear', 'height': 400, 'width': 450, })
plot(df,config={'insight.missing.threshold':20, 'insight.duplicates.threshold':20})
Facet Dive
【2017-7-30】Google开发的数据可视化web工具Facet Dive
【2018-3-13】可以嵌入jupyter notebook做特征工程可视化分析, 安装方法参考PAIR-CODE,Google AI
【2018-9-11】集成到tensorboard工具中:what-if
【2020-1-8】北京大学高维数据可视化
Bamboolib
媲美 Jupyter Notebook 的交互式数据分析库:Bamboolib(数据可视化篇)
- 无需写代码
pip install bamboolib
#pip install --upgrade bamboolib --user
使用方法
import bamboolib as bam
# Type bam > Read CSV file > Navigate to your file > Choose the file name > Open CSV file
bam # type
PyGWalker
【2024-10-6】PyGWalker 将 pandas DataFrame 数据交互可视化
安装
pip install pygwalker --upgrade
示例
import pygwalker as pyg
import pandas as pd
df = pd.read_csv("data.csv")
pyg.walk(df)
DM软件
Weka
【2018-6-15】数据挖掘软件:
- weka适用于EDA探索性数据分析
Orange
- Orange数据挖掘和机器学习软件
OLAP工具
SAIKU
地图数据可视化
BI
Tableau
TabPy
(Tableau Python Server)是一种分析扩展实现,允许用户通过 Tableau 表计算执行Python脚本和保存的函数,从而扩展了Tableau的功能。
通过使用与Python编程集成的Tableau,可以创建多个动态的高级报告,并为ML集成做好准备。
好处是:
- 高级分析
- 机器学习就绪仪表板
- 高级计算
- 有效的探索性数据分析
安装
pip install tabpy==2.3.1
tabpy # 链接服务器
服务地址
本地 Tableau 软件
- ”Help” -> “Settings and Performance” -> “Manage External Service Connectiontableau”在tableau中连接tabpy。
- 端口号指定 9004 并登录。
- 用户可以选中”Require SSL”复选框以加密通过网络发送的数据。
- 最后,点击”Test Connection”,将显示后续连接成功。
Matplotlib
- Python 有非常丰富的第三方绘图库,matplotlib 使用起来也许并不是很便捷,因为图上每个元素都需要自己来定制。但仔细体会 matplotlib 背后的设计思想是很有趣的事情。seaborn 之类的绘图库是基于 matplotlib 封装的,因而后期需要自己灵活定制图形时就大大受用了。本文的两幅思维导图是基于两种不同的思路绘制的,偶有内容交叉,日常使用可以选择自己熟悉的方式(网上的教程大多是基于过程的函数式编程,即 pyplot 方法)。建议配合最后附上出的参考资料学习。
Reference
《Python for data analysis》
Matplotlib: Python plotting — Matplotlib 2.0.2 documentation
绘图: matplotlib核心剖析
【数据可视化】 之 Matplotlib
Python–matplotlib绘图可视化知识点整理
一份非常好的Matplotlib 教程
- 绘制热力图
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
# 这里是创建一个数据
vegetables = ["cucumber", "tomato", "lettuce", "asparagus",
"potato", "wheat", "barley"]
farmers = ["Farmer Joe", "Upland Bros.", "Smith Gardening",
"Agrifun", "Organiculture", "BioGoods Ltd.", "Cornylee Corp."]
harvest = np.array([[0.8, 2.4, 2.5, 3.9, 0.0, 4.0, 0.0],
[2.4, 0.0, 4.0, 1.0, 2.7, 0.0, 0.0],
[1.1, 2.4, 0.8, 4.3, 1.9, 4.4, 0.0],
[0.6, 0.0, 0.3, 0.0, 3.1, 0.0, 0.0],
[0.7, 1.7, 0.6, 2.6, 2.2, 6.2, 0.0],
[1.3, 1.2, 0.0, 0.0, 0.0, 3.2, 5.1],
[0.1, 2.0, 0.0, 1.4, 0.0, 1.9, 6.3]])
# 这里是创建一个画布
fig, ax = plt.subplots()
im = ax.imshow(harvest)
# 这里是修改标签
# We want to show all ticks...
ax.set_xticks(np.arange(len(farmers)))
ax.set_yticks(np.arange(len(vegetables)))
# ... and label them with the respective list entries
ax.set_xticklabels(farmers)
ax.set_yticklabels(vegetables)
# 因为x轴的标签太长了,需要旋转一下,更加好看
# Rotate the tick labels and set their alignment.
plt.setp(ax.get_xticklabels(), rotation=45, ha="right",
rotation_mode="anchor")
# 添加每个热力块的具体数值
# Loop over data dimensions and create text annotations.
for i in range(len(vegetables)):
for j in range(len(farmers)):
text = ax.text(j, i, harvest[i, j],
ha="center", va="center", color="w")
ax.set_title("Harvest of local farmers (in tons/year)")
fig.tight_layout()
plt.colorbar(im)
plt.show()
from matplotlib import pyplot as plt
from matplotlib import cm as cm
def correlation_matrix(df):
fig = plt.figure(figsize=(50,30))
ax1 = fig.add_subplot(111)
ax1.set_title('intent translate map',fontsize=40,color='b')
cmap = cm.get_cmap('jet', 30)
cax = ax1.imshow(df.corr(), interpolation="nearest", cmap=cmap)
ax1.grid(True)
#plt.title('Abalone Feature Correlation')
labels_x = df.index
labels_y = df.columns
#labels=['Sex','Length','Diam','Height','Whole','Shucked','Viscera','Shell','Rings',]
ax1.set_xticklabels(labels_x,fontsize=20)
ax1.set_yticklabels(labels_y,fontsize=20)
# Add colorbar, make sure to specify tick locations to match desired ticklabels
fig.colorbar(cax, ticks=[.75,.8,.85,.90,.95,1])
plt.show()
correlation_matrix(df)
turtle
- 【2021-4-6】Python的turtle库使用-画出好看的图形,1969年诞生,Python语言的标准库之一,入门级的图形绘制函数库, 官方文档, 入门指南
- 布局
- 示例, 彩色螺旋线
import turtle
turtle.shape('turtle')
turtle.speed(9) # 画笔速度
turtle.pensize(2) # 画笔的宽度
turtle.bgcolor("black") # 画布背景色
colors = ["red","yellow","green","blue"] # 定义画笔线色
for i in range(255): # 循环一次 画一条线
turtle.forward(2 * i) # 向当前方向前进n像素
turtle.color(colors[i % 4]) # 根据求余 调整画笔线色
turtle.left(91) # 向左旋转91度
turtle.done()
streamlit
Streamlit简介
Streamlit 是 Python 的一个用于创建 Web App 的框架,类似于 R 的 Shiny。其功能虽不如 R Shiny 强大,更不如专门的 Python Web 框架如 Flask、Djiango 等强大,但其使用非常直观和简单,不需要过多的 Web 知识。如果之前用过 Markdown 或 Jupyter Notebook 等,便能快速上手,创建自己的 Web App。
Streamlit 的使用场景,如:
- 研究开发了一个临床预测模型,使用 Streamlit 将该预测模型搭建在网站上随论文发表或供别人体检。
- 公司某部门人员需要批量处理 Excel 文件,因而可以写一个 python 脚本自动化处理;但部门人员并不会用 python、也未安装 python 环境,此时便可将该脚本使用 Streamlit 部署成 Web App,部门人员使用时只需点击上传 Excel 文件,然后点击下载处理完成的文件即可。
Streamlit 安装
Streamlit 安装
pip install streamlit # 安装
streamlit hello # 创建本地app
命令行中运行:streamlit hello,便可创建一个本地的 Web App,点击 URL 地址(http://localhost:8502)在浏览器打开
Streamlit 自定义app
Streamlit 写 App 就是创建一个 py 文件,而不需要分别创建前端和后端。
import streamlit as st
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
# 展示文本;文本直接使用Markdown语法
st.markdown("# Streamlit示例")
st.markdown("""
- 这是
- 一个
- 无序列表
""")
# 展示pandas数据框
st.dataframe(pd.DataFrame([[1, 2], [3, 4]], columns=["a", "b"]))
# 展示matplotlib绘图
arr = np.random.normal(1, 1, size=100)
plt.hist(arr, bins=20)
plt.title("matplotlib plot")
st.pyplot()
# 加入交互控件,如输入框
number = st.number_input("Insert a number", 123)
st.write("输入的数字是:", number)
该 py 文件放在某文件夹下,cmd 中 cd 到该文件夹
- 输入命令
streamlit run example.py # 执行
streamlit run example.py --server.port 80 # 指定 App 在 80 端口运行
- 点击出现的 URL 后可见界面:
上述方式将 App 搭建在本地机上,如果想将 App 供别人访问,则需将 App 搭建在服务器如阿里云服务器或者部署在托管网站如 heroku 再或者使用内网穿透软件如 花生壳。
Streamlit 语法
Streamlit 主要用法总结
import streamlit as st
import pandas as pd
import numpy as np
import time
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.figure_factory as ff
import altair as alt
from PIL import Image
import base64
文字、公式
对照输出查看显示效果
st.title("st.title")
st.header("st.header")
st.subheader("st.subheader")
st.markdown("# markdown一级标题")
st.markdown("## markdown二级标题")
st.markdown("### markdown三级标题")
# ------------------------------------
st.write("st.write")
st.markdown("markdown普通文字")
st.text("st.text")
# ------------------------------------
st.markdown("""
Markdown列表:
- hello
- world
- China
""")
st.markdown("***markdown粗斜体***")
# ------------------------------------
st.latex("\sum_{i=1}^{n}")
# ------------------------------------
st.write(1234)
st.write("1234")
st.write("1 + 1 = ", 2)
st.write()
st.write () 是一个泛型函数,根据传入对象不同采取不同的展示方式,比如传入 pandas.DataFrame 时,st.write (df) 默认调用 st.dataframe (),传入 markdown 时,st.write (markdown) 默认调用 st.markdown ();跟 R 的泛型函数非常类似。可传入的对象有:
- write(data_frame) : Displays the DataFrame as a table.
- write(func) : Displays information about a function.
- write(module) : Displays information about the module.
- write(dict) : Displays dict in an interactive widget.
- write(obj) : The default is to print str(obj).
- write(mpl_fig) : Displays a Matplotlib figure.
- write(altair) : Displays an Altair chart.
- write(keras) : Displays a Keras model.
- write(graphviz) : Displays a Graphviz graph.
- write(plotly_fig) : Displays a Plotly figure.
- write(bokeh_fig) : Displays a Bokeh figure.
- write(sympy_expr) : Prints SymPy expression using LaTeX.
- write(markdown):
# 字典
st.write({"a": [1, 2, 3],
"b": [2, 3, 4]})
# pandas数据框
st.write(pd.DataFrame({
"a": [1, 2, 3, 4, 5],
"b": [4, 5, 6, 7, 8]
}))
# Markdown文字
st.write("Hello, *World!* :sunglasses:")
# 绘图对象
df = pd.DataFrame(
np.random.randn(200, 3),
columns=["a", "b", "c"]
)
c = alt.Chart(df).mark_circle().encode(
x="a", y="b", size="c", color="c", tooltip=["a", "b", "c"])
st.write(c)
表格
两种表格,动态表格和静态表格
# 动态表格(表格太大时只展示一部分,可滑动表格下方滑动条查看不同部分)
# st.write默认调用st.dataframe()
df = pd.DataFrame(
np.random.randn(10, 20),
columns=('col %d' % i for i in range(20)))
st.write(df)
# 静态表格(展示表格全部内容,太大时滑动App界面下方的滑动条查看不同部分)
df = pd.DataFrame({
"a": [1, 2, 3, 4, 5],
"b": [4, 5, 6, 7, 8]
})
st.table(df)
# pandas.DataFrame 的 style 也可正常显示
df = pd.DataFrame(
np.random.randn(10, 20),
columns=('col %d' % i for i in range(20)))
st.dataframe(df.style.highlight_max(axis=0))
动态扩增表格或动态绘图
- 表格、图片可以使用 add_rows() 方法添加新数据
df1 = pd.DataFrame(
np.random.randn(5, 5),
columns=("col %d" % i for i in range(5))
)
tb_table = st.table(df1)
for i in range(10):
df2 = pd.DataFrame(
np.random.randn(1, 5),
columns=("col %d" % i for i in range(5))
)
tb_table.add_rows(df2)
time.sleep(0.5)
Code
仅展示 Code,Code 不执行
code = """
def sum_(x):
return np.sum(x)
"""
st.code(code, language="python")
code = """
for (i i 1:10) {
print(i)
}
"""
st.code(code, language="r")
st.markdown("""
```python
print("hello")
""")
展示 Code,同时执行 Code;需要将 code 放入 st.echo() 内
with st.echo():
for i in range(5):
st.write("hello")
各种控件
# 数字输入框
number = st.number_input("Insert a number", 123)
# 单行文本输入框
word = st.text_input("Insert a word", "123")
st.write("The number is", number, "The word is", word)
# 多行文本输入框
st.text_area("Text to analyze", "I love China")
# 日期输入框
st.date_input("Insert a date")
# 时间输入框
st.time_input("Insert a time")
# 点击按钮
number = st.button("click it")
st.write("返回值:", number)
# 滑动条
x = st.slider("Square", min_value=0, max_value=80)
st.write(x, "squared is", np.power(x, 2))
# 检查框
res = st.checkbox("I agree")
st.write(res)
# 单选框
st.selectbox("Which would you like", [1, 2, 3])
# 单选按钮
st.radio("Which would you like", [1, 2, 3])
# 多选框
selector = st.multiselect("Which would you like", [1, 2, 3])
st.write(selector)
上传 csv 文件
uploaded_file = st.file_uploader("Choose a CSV file", type="csv")
if uploaded_file is not None:
data = pd.read_csv(uploaded_file)
st.write(data)
下载:
- 目前 Streamlit 还没有专门的下载控件,下载 pandas Dataframe 为 csv 文件可通过以下方式实现
- 点击 Download CSV File 便可下载文件
data = [(1, 2, 3)]
df = pd.DataFrame(data, columns=["Col1", "Col2", "Col3"])
csv = df.to_csv(index=False)
b64 = base64.b64encode(csv.encode()).decode()
href = f'<a href="data:file/csv;base64,{b64}">Download CSV File</a> (right-click and save as <some_name>.csv)'
st.markdown(href, unsafe_allow_html=True)
侧边栏控件
以上控件大部分都有对应的侧边栏形式,如上述 st.selectbox 若想放置在侧边栏,可使用 st.sidebar.selectbox
# 单选框
st.sidebar.selectbox("Which would you like", [1, 2, 3], key="1")
# 单选按钮
st.sidebar.radio("Which would you like", [1, 2, 3], key="1")
# 多选框
selector = st.sidebar.multiselect("Which would you like", [1, 2, 3], key="3")
st.write(selector)
绘图、图片、音频、视频
支持的绘图库:
- streamlit 自带绘图:st.line_chart()、bar_chart() 等
- matplotlib 或 seaborn:st.pyplot()
- altair:st.altair_chart()
- vega: st.vega_lite_chart()
- plotly: st.plotly_chart()
- bokeh: st.bokeh_chart()
streamlit 自带绘图
- st.line_chart() 和 st.bar_chart()
st.line_chart(np.random.randn(10, 2))
chart_data = pd.DataFrame(
np.random.randn(50, 3),
columns=["a", "b", "c"]
)
st.bar_chart(chart_data)
matplotlib 或 seaborn 绘图
st.markdown("# matplotlib绘图")
arr = np.random.normal(1, 1, size=100)
plt.hist(arr, bins=20)
st.pyplot()
st.markdown("# seaborn绘图")
tips = sns.load_dataset("tips")
sns.set(style="darkgrid")
sns.scatterplot(x="total_bill", y="tip", hue="smoker", data=tips)
st.pyplot()
地图
# 绘制1000个点的坐标
map_data = pd.DataFrame(
np.random.randn(1000, 2) / [50, 50] + [37.76, -122.4],
columns=['lat', 'lon'])
st.map(map_data)
展示图片、音频、视频
- 图片:st.image ()
- 音频:st.audio ()
- 视频:st.video ()
状态
st.error("错误显示为")
st.warning("警告显示为")
st.info("普通消息显示为")
st.success("成功消息显示为")
进度条
# 添加占位符
placeholder = st.empty()
# 创建进度条
bar = st.progress(0)
for i in range(100):
time.sleep(0.05)
# 不断更新占位符的内容
placeholder.text(f"Iteration {i+1}")
# 不断更新进度条
bar.progress(i + 1)
# 状态
st.success("Finished")
等待条
with st.spinner("Wait for it..."):
for i in range(100):
print("hello")
time.sleep(0.05)
st.success("Done!")
seaborn
- 建立在matplotlib上
- Seaborn的heatmap参数介绍
- data:矩阵数据集,可以使numpy的数组(array),如果是pandas的dataframe,则df的index/column信息会分别对应到heatmap的columns和rows
- linewidths,热力图矩阵之间的间隔大小
- vmax,vmin, 图例中最大值和最小值的显示值,没有该参数时默认不显示
- cmap:matplotlib的colormap名称或颜色对象;如果没有提供,默认为cubehelix map (数据集为连续数据集时) 或 RdBu_r (数据集为离散数据集时)
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
import random
np.random.seed(1)
data = np.random.rand(16, 16)
sns.set()
ax = sns.heatmap(data, center=0)
#plt.savefig('res.png', dpi=300)
plt.show()
f, (ax1,ax2) = plt.subplots(figsize = (10, 8),nrows=2)
# cubehelix map颜色
cmap = sns.cubehelix_palette(start = 1.5, rot = 3, gamma=0.8, as_cmap = True)
sns.heatmap(pt, linewidths = 0.05, ax = ax1, vmax=15000, vmin=0, cmap=cmap)
ax1.set_title('cubehelix map')
ax1.set_xlabel('')
ax1.set_xticklabels([]) #设置x轴图例为空值
ax1.set_ylabel('kind')
# matplotlib colormap
sns.heatmap(pt, linewidths = 0.05, ax = ax2, vmax=15000, vmin=0, cmap='rainbow')
# rainbow为 matplotlib 的colormap名称
ax2.set_title('matplotlib colormap')
ax2.set_xlabel('region')
ax2.set_ylabel('kind')
f.savefig('sns_heatmap_cmap.jpg', bbox_inches='tight')
# 加数值标注
np.random.seed(0)
x = np.random.randn(10, 10)
f, (ax1, ax2) = plt.subplots(figsize=(8,8),nrows=2)
sns.heatmap(x, annot=True, ax=ax1)
sns.heatmap(x, annot=True, fmt='.1f', ax=ax2)
f.savefig('sns_heatmap_fmt.jpg')
pyecharts
简介
Echarts是一个由百度开源的数据可视化工具,凭借着良好的交互性,精巧的图表设计,得到了众多开发者的认可。pyecharts是一个全新的可视化绘图工具,因此它的绘图逻辑完全不同于前面说到的matplotlib、seaborn、plotly。
- 【2018-3-5】python+echarts给你的数据做美颜,pycharts安装,官方文档,jupyter notebook中使用pycharts,github代码完整示例,【2019-05-22】pyechart旧版绘图参数介绍-官网没有,效果示例:
版本
- 【2020-12-08】pyecharts分为v0.5和v1两个大版本,v0.5和v1两个版本不兼容,风格迥异,v1是一个全新的版本。旧版基本放弃。
- 查看版本:print(pyecharts.version)
- 旧版是过程式调用,新版是链式调用
安装
命令:
pip install pyecharts
# 如果需要绘制地图,下列地图数据包需要安装
pip install echarts-countries-pypkg
pip install echarts-china-provinces-pypkg
pip install echarts-china-cities-pypkg
pip install echarts-china-counties-pypkg
pip install echarts-china-misc-pypkg
- pyecharts官网,示例程序
注意:
- 在使用 Pandas&Numpy 时,请确保将数值类型转换为 python 原生的 int/float。比如整数类型请确保为 int,而不是 numpy.int32
效果展示
echarts效果大全
基础知识
pyecharts的绘图逻辑分为以下几步。
- ① 选择图表类型;散点、折线、饼图以及地图等
- from pyecharts.charts import Scatter
- ② 声明图形类并添加数据;每一个图形库都是被pyecharts作者封装成为了一个类,即面向对象,用类时,需要实例化这个类。声明类之后,相当于初始化了一个画布,之后的绘图就是在这个画布上进行。接下来要做的就是添加数据,pyecharts中添加数据共有2种方式,一种是普通的过程式添加数据,一种是链式调用(观察下面代码)来添加数据
- 散点图、折线图等二维数据图形,它既有X轴,又有Y轴,两个轴都要添加
- .add_xaxis(xaxis_data=x)为X轴添加数据;
- .add_yaxis(series_name=’’, y_axis=y)为Y轴添加数据;series_name参数必须有,添加的数据标题
- 饼图、地图没有X轴、Y轴区分的图形,直接使用add()方法添加即可
- .add(series_name=’’, data_pair=[(i,j)for i,j in zip(lab,num)]);
- 散点图、折线图等二维数据图形,它既有X轴,又有Y轴,两个轴都要添加
- ③ 选择全局变量;调节各种各样的参数,把图形变得更好看. 常用的有: 图片总结
标题
配置项: TitleOpts图例
配置项: LegendOpts工具
配置项: ToolboxOpts视觉映射
配置项: VisualMapOpts提示框
配置项: TooltipOpts区域缩放
配置项: DataZoomOpts- 还有初始化画布大小:InitOpts,示例:
- import pyecharts.options as opts
- pie = Pie(init_opts=opts.InitOpts(width=”700px”,height=”300px”))
- ④ 显示及保存图表;
- render(‘a.html’) # html格式展示,链接分享
- render_notebook() # 渲染到jupyter notebook
# 1.选择图表类型:我们使用的是散点图,就直接从charts模块中导入Scatter这个图形。
from pyecharts.charts import Scatter
import numpy as np
x = np.linspace(0,2 * np.pi,100)
y = np.sin(x)
(
# 注意:使用什么图形,就要实例化该图形的类;
# 2.我们绘制的是Scatter散点图,就需要实例化散点图类,直接Scatter() 即可;
Scatter()
# 实例化类后,接着就是添加数据,下面这种方式就是使用“链式调用”的方式绘图;
# 注意:散点图有X、Y轴,因此需要分别给X轴、Y轴添加数据;
# 3.我们先给X轴添加数据;
.add_xaxis(xaxis_data=x)
# 4.我们再给Y轴添加数据;
.add_yaxis(series_name="这个图是干嘛的",y_axis=y)
).render_notebook()
画布型号——版面
代码
from pyecharts.charts import Bar
from pyecharts import options as opts
bar = (
Bar(init_opts=opts.InitOpts(width="1700px",
height="750px",
page_title="画布大小设置"))
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
.add_yaxis("商家B", [15, 6, 45, 20, 35, 66])
.set_global_opts(title_opts=opts.TitleOpts(title="商家销售汇总",subtitle="分类汇总"))
#.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题"))
)
bar.render("123.html")
画布主题——版面/标题
代码: 主题效果大全
- Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
from pyecharts.charts import Bar
from pyecharts import options as opts
# 内置主题类型可查看 pyecharts.globals.ThemeType
from pyecharts.globals import ThemeType
bar = (
Bar(init_opts=opts.InitOpts(width="1700px",
height="750px",
page_title="画布设置",
theme=ThemeType.DARK))
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
.add_yaxis("商家B", [15, 6, 45, 20, 35, 66])
.set_global_opts(title_opts=opts.TitleOpts(title="商家销售汇总",subtitle="分类汇总"))
#.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题"))
)
bar.render("123.html")
坐标轴设置
type_ :坐标轴类型, 可选:
- ‘value’ 数值轴,适用于连续数据。
- ‘category’ 类目轴,适用于离散的类目数据
- ‘time’ 时间轴,适用于连续的时序数据,与数值轴相比时间轴带有时间的格式化,在刻度计算上也有所不同,例如会根据跨度的范围来决定使用月,星期,日还是小时范围的刻度。
- ‘log’ 对数轴。适用于对数数据。
from random import randint
from pyecharts import options as opts
from pyecharts.charts import Bar
from pyecharts.commons.utils import JsCode
x_data = ['分类1','分类2','分类3','分类4','分类5',]
y1_data = [0.72,0.61,0.98,0.92,0.67,]
y2_data = [d * randint(1, 10) for d in y1_data]
instance_bar = (
Bar()
.add_xaxis(xaxis_data=x_data)
.add_yaxis(series_name='系列1', yaxis_data=y1_data)
.add_yaxis(series_name='系列2', yaxis_data=y2_data)
.set_global_opts( # 全局设置
xaxis_opts=opts.AxisOpts( # (1)x轴设置
type_='category', # value数值轴,category类目轴,time时间轴,log对数轴
name='x名称', # Optional[str]
is_show=True, # bool, 是否显示坐标轴
is_scale=False, # bool,坐标刻度是否包含零刻度,只在数值轴中(type: ‘value’)有效。设置成 true 后坐标刻度不会强制包含零刻度。在双数值轴的散点图中比较有用。在设置 min 和 max 之后该配置项无效
is_inverse=True, # bool,是否是反向坐标轴
name_location='start', # str,坐标轴名称显示位置,'start','middle'/'center','end'
name_gap=15, # Numeric,坐标轴名称与轴线之间的距离
name_rotate=20, # Optional[Numeric],坐标轴名字旋转,角度值
name_textstyle_opts=opts.TextStyleOpts( # (2)坐标轴名称的文字样式
color='blue', # 颜色
font_style=None, # 字体,可选:‘normal’,‘italic’,‘oblique’
font_weight=None, # 粗细,可选:‘normal’,‘bold’,‘bolder’,‘lighter’
font_family=None, # 字体, ‘serif’ , ‘monospace’, ‘Arial’, ‘Courier New’, ‘Microsoft YaHei’, …
font_size=None, # 字体大小
align=None, # 水平对齐方式,默认自动
vertical_align=None, # 垂直对齐方式,默认自动
line_height=None, # 行高
background_color='yellow', # 文字块背景色。可以是直接的颜色值,例如:’#123234’, ‘red’, ‘rgba(0,23,11,0.3)’
border_color=None, # 文字块边框颜色
border_width=None, # 文字块边框高度
border_radius=None, # 文字块的圆角
padding=None, # Union[Numeric, Sequence, None],文字块的内边距。例:padding: [3, 4, 5, 6]:表示 [上, 右, 下, 左] 的边距,padding: 4:表示 padding: [4, 4, 4, 4],padding: [3, 4]:表示 padding: [3, 4, 3, 4]
shadow_color=None, # 文字块的背景阴影颜色
shadow_blur=None, # 文字块的背景阴影长度
width=None, # 文字块的宽度
height=None, # 文字块的高度
rich=None, # Optional[dict],自定义富文本样式
),
interval=30, # Optional[Numeric],坐标轴间隔,强制设置坐标轴分割间隔。无法在类目轴中使用。在时间轴(type: ‘time’)中需要传时间戳,在对数轴(type: ‘log’)中需要传指数值
grid_index=0, # Numeric,坐标轴所在的 grid 的索引,默认位于第一个 grid
position='', # Optional[str],坐标轴位置可选:'top','bottom',默认 grid 中的第一个 x 轴在 grid 的下方('bottom'),第二个 x 轴视第一个 x 轴的位置放在另一侧
offset=0, # Numeric,坐标轴偏移,X 轴相对于默认位置的偏移,在相同的 position 上有多个 X 轴的时候有用
split_number=5, # Numeric,坐标轴的分割段数,需要注意的是这个分割段数只是个预估值,最后实际显示的段数会在这个基础上根据分割后坐标轴刻度显示的易读程度作调整。在类目轴中无效。
boundary_gap='', # Union[str, bool, None],坐标轴两边留白策略。类目轴和非类目轴的设置和表现不一样。类目轴中 boundaryGap 可以配置为 true 和 false。默认为 true,这时候刻度只是作为分隔线,标签和数据点都会在两个刻度之间的带(band)中间。非类目轴,包括时间,数值,对数轴,boundaryGap是一个两个值的数组,分别表示数据最小值和最大值的延伸范围,可以直接设置数值或者相对的百分比,在设置 min 和 max 后无效。boundaryGap: [‘20%’, ‘20%’]
min_='', # Union[Numeric, str, None],坐标轴最小值
max_='', # Union[Numeric, str, None],坐标轴最大值
min_interval=0, # Numeric,坐标轴最小间隔,自动计算的坐标轴最小间隔大小。例如可以设置成1保证坐标轴分割刻度显示成整数。只在数值轴或时间轴中(type: ‘value’ 或 ‘time’)有效。
max_interval=0, # Optional[Numeric] ,坐标轴最大间隔,自动计算的坐标轴最大间隔大小。例如,在时间轴((type: ‘time’))可以设置成 3600 * 24 * 1000 保证坐标轴分割刻度最大为一天。只在数值轴或时间轴中(type: ‘value’ 或 ‘time’)有效。
axisline_opts=opts.AxisLineOpts( # (3)坐标轴轴线相关设置
is_show=True, # 是否显示坐标轴轴线。
is_on_zero=True, # X 轴或Y 轴的轴线是否在另一个轴的 0 刻度上,只有在另一个轴为数值轴且包含 0 刻度时有效。
on_zero_axis_index=0,
symbol=None,
linestyle_opts=opts.LineStyleOpts( # 坐标轴线风格配置项
is_show=True,
width=1,
opacity=1,
curve=0,
type_="solid",
color=None,
)
),
axistick_opts=opts.AxisTickOpts( # (4)坐标轴刻度相关设置
is_show=True,
is_align_with_label=True,
is_inside=True,
length=20,
linestyle_opts=opts.LineStyleOpts(
is_show=True,
width=1,
opacity=1,
curve=0,
type_="solid",
color=None,
)
),
axislabel_opts=opts.LabelOpts(
is_show=True, # bool
position="top", # Union[str, Sequence]
color='pink', # Optional[str]
font_size=None, # Optional[Numeric]
font_style=None, # Optional[str]
font_weight=None, # Optional[str]
font_family=None, # Optional[str]
rotate=10, # Optional[Numeric]
margin=8, # Optional[Numeric]\,
interval=None, # Union[Numeric, str, None]
horizontal_align=None, # Optional[str]
vertical_align=None, # Optional[str]
formatter=JsCode("""
function(value,index) {
if (index === 2) {
return 'formatter';
} else {
return value;
}
}
"""), # Optional[JSFunc] 回调函数
# 字符串模板 formatter='-{value}-',
background_color=None, # Optional[str]
border_color=None, # Optional[str]
border_width=None, # Optional[Numeric]
border_radius=None, # Optional[Numeric]
rich=None, # Optional[dict]
),
axispointer_opts=opts.AxisPointerOpts( # 坐标轴指示器设置
is_show=True,
link=None,
type_="line",
label=None,
linestyle_opts=opts.LineStyleOpts(
is_show=True,
width=10,
opacity=0.5,
curve=0,
type_="solid",
color='green',
),
),
splitarea_opts=opts.SplitAreaOpts( # 坐标轴在 grid 区域中的分隔区域设置
is_show=True,
areastyle_opts=opts.AreaStyleOpts(
opacity=0.05,
color={
'type': 'linear',
'x': 0,
'y': 0,
'x2': 0,
'y2': 1,
'colorStops': [{
'offset': 0, 'color': 'red' # 0% 处的颜色
}, {
'offset': 1, 'color': 'blue' # 100% 处的颜色
}],
'global': False # 缺省为 false
}
)
),
splitline_opts=opts.SplitLineOpts( # 坐标轴在 grid 区域中的分隔线设置
is_show=True,
linestyle_opts=opts.LineStyleOpts(
is_show=True,
width=1,
opacity=1,
curve=0,
type_="solid",
color='#0099ff',
)
)
)
)
)
视觉映射
class pyecharts.options.VisualMapOpts
class VisualMapOpts(
is_show: bool = True,# 是否显示视觉映射配置
type_: str = "color",# 映射过渡类型,可选,"color", "size"
min_: Union[int, float] = 0,# 指定 visualMapPiecewise 组件的最小值
max_: Union[int, float] = 100, # 指定 visualMapPiecewise 组件的最大值
range_text: Union[list, tuple] = None,# 两端的文本,如['High', 'Low']
range_color: Union[Sequence[str]] = None,# visualMap 组件过渡颜色
range_size: Union[Sequence[int]] = None,# visualMap 组件过渡 symbol 大小
orient: str = "vertical",# 如何放置 visualMap 组件,水平('horizontal')或者竖直('vertical')
# visualMap 组件离容器左侧的距离
# left 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比,
# 也可以是 'left', 'center', 'right'。
# 如果 left 的值为'left', 'center', 'right',组件会根据相应的位置自动对齐
pos_left: Optional[str] = None,
# visualMap 组件离容器右侧的距离
# right 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比
pos_right: Optional[str] = None,
# visualMap 组件离容器上侧的距离
# top 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比
# 也可以是 'top', 'middle', 'bottom'
# 如果 top 的值为'top', 'middle', 'bottom',组件会根据相应的位置自动对齐
pos_top: Optional[str] = None,
# visualMap 组件离容器下侧的距离。
# bottom 的值可以是像 20 这样的具体像素值,可以是像 '20%' 这样相对于容器高宽的百分比。
pos_bottom: Optional[str] = None,
split_number: int = 5, # 对于连续型数据,自动平均切分成几段。默认为5段。连续数据的范围需要 max 和 min 来指定
series_index: Union[Numeric, Sequence, None] = None,# 指定取哪个系列的数据,默认取所有系列
dimension: Optional[Numeric] = None,# 组件映射维度
is_calculable: bool = True, # 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)
is_piecewise: bool = False,# 是否为分段型
# 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
# pieces: [
# {"min": 1500}, // 不指定 max,表示 max 为无限大(Infinity)
# {"min": 900, "max": 1500},
# {"min": 310, "max": 1000},
# {"min": 200, "max": 300},
# {"min": 10, "max": 200, "label": '10 到 200(自定义label)'},
# {"value": 123, "label": '123(自定义特殊颜色)', "color": 'grey'}, //表示 value 等于 123 的情况
# {"max": 5} // 不指定 min,表示 min 为无限大(-Infinity)
# ]
pieces: Optional[Sequence] = None,
# 定义 在选中范围外 的视觉元素(用户可以和 visualMap 组件交互,用鼠标或触摸选择范围)
# 可选的视觉元素有:
# symbol: 图元的图形类别
# symbolSize: 图元的大小
# color: 图元的颜色
# colorAlpha: 图元的颜色的透明度
# opacity: 图元以及其附属物(如文字标签)的透明度
# colorLightness: 颜色的明暗度,参见 HSL
# colorSaturation: 颜色的饱和度,参见 HSL
# colorHue: 颜色的色调,参见 HSL
out_of_range: Optional[Sequence] = None,
item_width: int = 0, # 图形的宽度,即长条的宽度
item_height: int = 0, # 图形的高度,即长条的高度
textstyle_opts: Union[TextStyleOpts, dict, None] = None,# 文字样式配置项,参考 `series_options.TextStyleOpts`
)
.set_global_opts(visualmap_opts=opts.VisualMapOpts())#调用方法
基础设置示例
以bar图为例,展示各种属性的用法
from pyecharts.charts import Bar
#===========过程式调用==========
bar = Bar()
bar.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
# render 会生成本地 HTML 文件,默认会在当前目录生成 render.html 文件
# 也可以传入路径参数,如 bar.render("mycharts.html")
bar.render()
#============链式调用==========
from pyecharts.charts import Bar
bar = (
Bar()
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
)
bar.render()
- 使用 options 配置项,在 pyecharts 中,一切皆 Options。
from pyecharts.charts import Bar
from pyecharts import options as opts
# V1 版本开始支持链式调用
# 你所看到的格式其实是 `black` 格式化以后的效果
# 可以执行 `pip install black` 下载使用
bar = (
Bar()
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题"))
# 或者直接使用字典参数
# .set_global_opts(title_opts={"text": "主标题", "subtext": "副标题"})
)
bar.render()
# 不习惯链式调用的开发者依旧可以单独调用方法
bar = Bar()
bar.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
bar.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题"))
bar.render()
# 设置主题
from pyecharts.globals import ThemeType
bar = (
Bar(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
.add_xaxis(["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"])
.add_yaxis("商家A", [5, 20, 36, 10, 75, 90])
.add_yaxis("商家B", [15, 6, 45, 20, 35, 66])
.set_global_opts(title_opts=opts.TitleOpts(title="主标题", subtitle="副标题"))
)
# 更完整的示例
from pyecharts.charts import Bar
from pyecharts import options as opts
# V1 版本开始支持链式调用
bar = (
Bar()
# Bar({"theme": ThemeType.MACARONS}) # 设置主题
.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
.add_yaxis("商家B", Faker.values(),
is_selected=False, # 该列默认不选中!legend中无显示
stack="stack1", # 数值堆叠
category_gap="50%", # 设置间隔,与柱形宽度一样
color="", # 设置柱条颜色, 可传列表
)
#.add_yaxis("商家B", Faker.values(), stack="stack1", category_gap=0, color=Faker.rand_color())
.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
#.reversal_axis() # X/Y轴转置显示
# .set_series_opts(label_opts=opts.LabelOpts(is_show=False)) # 关闭数值显示
# 自定义数值展示内容
.set_series_opts(
label_opts=opts.LabelOpts(
position="right", # 靠右
formatter=JsCode( # 自定义计算数值, 原始数据格式:[{"value":3, "percent":0.23},{"value":5, "percent":0.43}], x.data指向每个元素
"function(x){return Number(x.data.percent * 100).toFixed() + '%';}"
),
),
# 标记每组数据的特殊值(x轴气泡显示):最小、最大、平均
markpoint_opts=opts.MarkPointOpts(
data=[
opts.MarkPointItem(type_="max", name="最大值"),
opts.MarkPointItem(type_="min", name="最小值"),
opts.MarkPointItem(type_="average", name="平均值"),
]
),
# 标记每组数据的特殊值:y轴用虚横线显示, https://gallery.pyecharts.org/#/Bar/bar_markline_type
markline_opts=opts.MarkLineOpts(
data=[
opts.MarkLineItem(type_="min", name="最小值"),
opts.MarkLineItem(type_="max", name="最大值"),
opts.MarkLineItem(type_="average", name="平均值"),
opts.MarkLineItem(y=50, name="yAxis=50") # 自定义取值
]
),
# 柱条形状变更:长方形 → 渐变椭圆圆柱
itemstyle_opts={
"normal": {
"color": JsCode(
"""new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: 'rgba(0, 244, 255, 1)'
}, {
offset: 1,
color: 'rgba(0, 77, 167, 1)'
}], false)"""
),
"barBorderRadius": [30, 30, 30, 30],
"shadowColor": "rgb(0, 160, 221)",
}
}
)
.set_global_opts(
title_opts=opts.TitleOpts(title="某商场销售情况",
subtitle='副标题\n第二行', # 支持换行
title_textstyle_opts=opts.TextStyleOpts(color="white"), # 设置文本颜色
),
# title_opts={"text": "Bar-通过 dict 进行配置", "subtext": "我也是通过 dict 进行配置的"} # 通过字典一次性设置
yaxis_opts=opts.AxisOpts(name="我是Y轴"),
xaxis_opts=opts.AxisOpts(name="我是X轴"),
# xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(rotate=-15)), # 向右旋转坐标轴文本15度
# yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} /月")), # 自定义y轴取值
#legend_opts=opts.LegendOpts(is_show=False), # 关闭图例
toolbox_opts=opts.ToolboxOpts(), # 显示工具箱
brush_opts=opts.BrushOpts(), # 刷子工具箱,框选范围(以上工具箱的子集)
datazoom_opts=opts.DataZoomOpts(), # 支持自由缩放(X轴)
#datazoom_opts=opts.DataZoomOpts(orient="vertical"), # 自由缩放(Y轴)
datazoom_opts=opts.DataZoomOpts(type_="inside"), # 隐性缩放,x轴没有缩放框,直接拖拽
datazoom_opts=[opts.DataZoomOpts(), opts.DataZoomOpts(type_="inside")], # 同时支持隐性+显性缩放
)
)
bar.render()
效果示例
注意事项
【2022-8-20】经验教训
- 使用pandas数据时,尤其注意转换列表!
- 用pandas的value_counts(频次统计)结果时,还需要注意转换类型(int64→int)!
- 参考: .add_yaxis添加纵坐标的值可视化后数据不显示
#!pip install pyecharts
from pyecharts.charts import Line, Bar, Page
from pyecharts import options as opts
import pandas as pd
df = pd.DataFrame({"name":["衬衫", "羊毛衫", "雪纺衫", "裤子", "高跟鞋", "袜子"], "num":[114, 55, 27, 101, 125, 27] })
raw_data = df['num'].value_counts().to_dict()
new_data = sorted(raw_data.items(), key=lambda x:x[0], reverse=False)
print(new_data)
bar = (
Bar()
.add_xaxis(list(df["name"])) # 使用pandas数据时,一定要注意转换成list!
.add_yaxis('pandas列数据', list(df['num'])) # 使用pandas数据时,一定要注意转换成list!
.set_global_opts(title_opts=opts.TitleOpts(title='pandas数据测试'))
)
line = (
Line()
.add_xaxis(raw_data.keys())
.add_yaxis('value_counts数据', [int(i) for i in raw_data.values()]) # 一定要转换数值类型:int64 → int
.set_global_opts(title_opts=opts.TitleOpts(title='pandas数据测试'))
)
bar1 = (
Bar() # 离散值用柱状图,否则line图空白
.add_xaxis([i[0] for i in new_data])
.add_yaxis('dict values', [i[1] for i in new_data])
.set_global_opts(title_opts=opts.TitleOpts(title='pandas数据测试'))
)
#bar.render_notebook()
page = Page(layout=Page.SimplePageLayout)
page.add(bar, line, bar1)
page.render_notebook()
#type(tmp_data[27])
图表详解
- 官方最全的代码+效果示例
表格展示
扩展组件:表格形式展示数据
from pyecharts.components import Table
from pyecharts.options import ComponentTitleOpts
table = Table()
headers = ["City name", "Area", "Population", "Annual Rainfall"]
rows = [
["Brisbane", 5905, 1857594, 1146.4],
["Adelaide", 1295, 1158259, 600.5],
["Darwin", 112, 120900, 1714.7],
["Hobart", 1357, 205556, 619.5],
["Sydney", 2058, 4336374, 1214.8],
["Melbourne", 1566, 3806092, 646.9],
["Perth", 5386, 1554769, 869.4],
]
# 排序
# sorted(rows, key=lambda x:x[1], reverse=True)
table.add(headers, rows)
table.set_global_opts(
title_opts=ComponentTitleOpts(title="Table-基本示例", subtitle="我是副标题支持换行哦")
)
table.render("table_base.html")
交互式表格
【2022-10-9】 streamlit 工具实现的交互式表格
import pandas as pd
import streamlit as st
from st_aggrid import AgGrid, GridOptionsBuilder
from st_aggrid.shared import GridUpdateMode
iris = pd.read_csv(
"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
)
def aggrid_interactive_table(df: pd.DataFrame):
"""Creates an st-aggrid interactive table based on a dataframe.
Args:
df (pd.DataFrame]): Source dataframe
Returns:
dict: The selected row
"""
options = GridOptionsBuilder.from_dataframe(
df, enableRowGroup=True, enableValue=True, enablePivot=True
)
options.configure_side_bar()
options.configure_selection("single")
selection = AgGrid(
df,
enable_enterprise_modules=True,
gridOptions=options.build(),
theme="light",
update_mode=GridUpdateMode.MODEL_CHANGED,
allow_unsafe_jscode=True,
)
return selection
iris = pd.read_csv(
"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv"
)
selection = aggrid_interactive_table(df=iris)
if selection:
st.write("You selected:")
st.json(selection["selected_rows"])
饼图
代码:
from pyecharts.charts import Pie
from pyecharts import options as opts
data = [['交易定金', 2],
['交易服务费', 3],
['交易流程-全款', 5],
['交易流程-公积金', 6],
['交易流程-商贷', 33],
['交易流程-组合贷', 2],
['征信与贷款', 2],
['户口保证金', 1],
['物业保证金', 3],
['税费政策', 14],
['解抵押流程', 7],
['贝壳服务内容', 15],
['资金监管', 18],
['限购限售政策', 1]]
pie = (Pie(init_opts=opts.InitOpts(width="1440px", height="720px"))
.add("交互成功的签约意图分布", data,
radius=["30%", "75%"], # radius=[40,75],radius:半径
center=["25%", "50%"],
rosetype="radius",
label_opts=opts.LabelOpts(is_show=True))
.set_global_opts(
title_opts=opts.TitleOpts(title="签约意图占比分布"), # TitleOpts:标题设置项
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
legend_opts=opts.LegendOpts(pos_top="5%",pos_right="15%", orient='vertical')) #LegendOpts:图例配置项
)
pie.render_notebook()
柱形图
from pyecharts.charts import Bar
from pyecharts import options as opts
# V1 版本开始支持链式调用
bar = (
Bar()
# Bar({"theme": ThemeType.MACARONS}) # 设置主题
.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
.add_yaxis("商家B", Faker.values(), stack="stack1") # 数值堆叠
.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"),
subtitle='副标题',
yaxis_opts=opts.AxisOpts(name="我是Y轴"),
xaxis_opts=opts.AxisOpts(name="我是X轴"),
#legend_opts=opts.LegendOpts(is_show=False), # 关闭图例
toolbox_opts=opts.ToolboxOpts(), # 显示工具箱
datazoom_opts=opts.DataZoomOpts(), # 支持自由缩放
)
)
bar.render()
# 不习惯链式调用的开发者依旧可以单独调用方法
bar = Bar()
bar.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
bar.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105]
# label_opts=opts.LabelOpts(is_show=False), # 不显示数值label
)
bar.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
bar.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"),
subtitle='副标题',
legend_opts=opts.LegendOpts(is_show=False), # 关闭图例
toolbox_opts=opts.ToolboxOpts(), # 显示工具箱
datazoom_opts=opts.DataZoomOpts(), # 支持自由缩放
)
#bar.render()
bar.render_notebook()
折线图
简版
from pyecharts.charts import Line
from pyecharts import options as opts
# V1 版本开始支持链式调用
bar = (
Line()
.add_xaxis(["衬衫", "毛衣", "领带", "裤子", "风衣", "高跟鞋", "袜子"])
.add_yaxis("商家A", [114, 55, 27, 101, 125, 27, 105])
.add_yaxis("商家B", [57, 134, 137, 129, 145, 60, 49])
.set_global_opts(title_opts=opts.TitleOpts(title="某商场销售情况"))
)
bar.render_notebook()
精细版
import pyecharts.options as opts
from pyecharts.charts import Line
"""
Gallery 使用 pyecharts 1.1.0
参考地址: https://echarts.apache.org/examples/editor.html?c=area-basic
目前无法实现的功能:
暂无
"""
x_data = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
y_data = [820, 932, 901, 934, 1290, 1330, 1320]
(
Line()
.add_xaxis(xaxis_data=x_data)
.add_yaxis(
series_name="",
y_axis=y_data,
symbol="emptyCircle",
is_symbol_show=True,
label_opts=opts.LabelOpts(is_show=False),
areastyle_opts=opts.AreaStyleOpts(opacity=1, color="#C67570"),
)
.set_global_opts(
tooltip_opts=opts.TooltipOpts(is_show=False),
yaxis_opts=opts.AxisOpts(
type_="value",
axistick_opts=opts.AxisTickOpts(is_show=True),
splitline_opts=opts.SplitLineOpts(is_show=True),
),
xaxis_opts=opts.AxisOpts(type_="category", boundary_gap=False),
)
# 设置 boundary_gap 的时候一定要放在最后一个配置项里, 不然会被覆盖
#.render("basic_area_chart.html")
.render_notebook()
)
树形图
多种效果
- 从左到右
- 从上到下
- 发散开:tree_layout
import json
from pyecharts import options as opts
from pyecharts.charts import Tree
with open("flare.json", "r", encoding="utf-8") as f:
j = json.load(f)
# 左右方向
c = (
Tree()
.add("", [j], collapse_interval=2)
.set_global_opts(title_opts=opts.TitleOpts(title="Tree-左右方向"))
.render("tree_left_right.html")
)
# 上下方向
c = (
Tree()
.add(
"",
[j],
collapse_interval=2,
orient="BT",
label_opts=opts.LabelOpts(
position="top",
horizontal_align="right",
vertical_align="middle",
rotate=-90,
),
)
.set_global_opts(title_opts=opts.TitleOpts(title="Tree-下上方向"))
.render("tree_bottom_top.html")
)
# 平铺
c = (
Tree()
.add("", [j], collapse_interval=2, layout="radial")
.set_global_opts(title_opts=opts.TitleOpts(title="Tree-Layout"))
.render("tree_layout.html")
)
数据格式
from pyecharts import options as opts
from pyecharts.charts import Tree
data = [
{
"children": [
{"name": "B"},
{
"children": [{"children": [{"name": "I"}], "name": "E"}, {"name": "F"}],
"name": "C",
},
{
"children": [
{"children": [{"name": "J"}, {"name": "K"}], "name": "G"},
{"name": "H"},
],
"name": "D",
},
],
"name": "A",
}
]
c = (
Tree()
.add("", data)
.set_global_opts(title_opts=opts.TitleOpts(title="Tree-基本示例"))
.render("tree_base.html")
)
桑基图 Sankey
- 桑基图:展现数据流动
- 桑基图主要由边、流量和支点组成,其中
边
代表了流动的数据.边的宽度与流量成比例地显示,边越宽,数值越大。流量
代表了流动数据的具体数值节点
代表了不同分类。
桑基图自被命名的那一刻起,就注定和能量分不开了。
- 桑基图通常用于可视化能源或成本转移,也帮助确定各部分流量在总体中的大概占比情况。无论数据怎么流动,桑基图的总数值保持不变,坚持数据的“能量守恒”。
- 无论数据怎样流动,数据的总量从开始到结束都不能有任何的变化,不能在中间过程创造出数据,流失(损耗)的数据应该流向表示损耗的支点。
- 与
弦图
不同,桑基图
的每条边的宽度是保持不变的。即使有时候出于设计需要,边的宽度看上去不一样,但所代表的数据是不变的。如果需要展示数据在流动过程中初始的权重变化,就应该使用弦图
。
桑基图在pyecharts中通过Sankey方法实现,它接受两个外部输入。
- 一个是所有类别的集合-nodes
- 一个是子类、父类、数据的三方集合-links。
这两个都是以json数据格式传入,最后以html形式输出图表。
# 导入相关库
import pandas as pd
from pyecharts.charts import Page, Sankey
from pyecharts import options as opts
# 读取csv文件
data = pd.read_csv(r'sample.csv',encoding='gbk',header=None)
# 生成nodes
nodes = []
nodes.append({'name':'总支出'})
for i in data[0].unique():
dic = {}
dic['name'] = i
nodes.append(dic)
# 生成links
links = []
for i in data.values:
dic = {}
dic['source'] = i[0]
dic['target'] = i[1]
dic['value'] = i[2]
links.append(dic)
# pyecharts 所有方法均支持链式调用。
c = (
Sankey()
.add(
"费用/元",
nodes,
links,
linestyle_opt=opts.LineStyleOpts(opacity=0.2, curve=0.5, color="source",type_="dotted"),
label_opts=opts.LabelOpts(position="right",),
)
.set_global_opts(title_opts=opts.TitleOpts(title="我的生活支出一览"))
)
# 输出html可视化结果
c.render('result.html')
动画
【2021-6-14】按照时间线轮播,kaggle代码地址
# -*- coding: UTF-8 -*-
import copy
import random
NUM = 10
wealth_list = [100]*NUM
person_id = [ '编号{}'.format(i) for i in range(NUM)]
print("迭代前的财富分配:{}".format(wealth_list))
wealth_process = {}
MAX = 1000000
stop = [1, 1000, 10000, 100000, MAX]
for iter in range(MAX):
for i,v in enumerate(wealth_list):
send_person = random.randint(0,NUM-1)
#print('第{}轮: {} -> {}'.format(iter, i, send_person))
#if wealth_list[i] > 0:
# wealth_list[i] -= 1
wealth_list[i] -= 1
wealth_list[send_person] += 1
if iter+1 in stop:
wealth_process[iter+1] = {'data': [], 'range':[]}
wealth_process[iter+1]['range'] = [min(wealth_list), max(wealth_list), max(wealth_list)/min(wealth_list),sum(wealth_list)/NUM]
wealth_process[iter+1]['data'] = copy.deepcopy(wealth_list)
print("迭代{}轮后的财富分配:[{},{}], 极差:{}, 均值:{}, 详情:{}".format(iter+1,
*wealth_process[iter+1]['range'], wealth_process[iter+1]['data']))
print("迭代{}轮后的财富分配:{}".format(iter+1, wealth_list))
from pyecharts import options as opts
from pyecharts.charts import Bar, Timeline
from pyecharts.commons.utils import JsCode
#from pyecharts.faker import Faker
#x = Faker.choose()
x = person_id
tl = Timeline()
for i in wealth_process:
bar = (
Bar()
.add_xaxis(x)
.add_yaxis("财富值", wealth_process[i]['data'])
#.add_yaxis("商家B", Faker.values())
.set_global_opts(
#title_opts=opts.TitleOpts("幂律分布:财富随机分配实验,第{}轮".format(i)),
title_opts=opts.TitleOpts(title="幂律分布:财富随机分配实验",
subtitle="{}人,每人底钱100元,每轮随机给别人1元,迭代{}轮后,[{},{}], 均值{:.2f}, 极差{}".format(NUM, MAX,
*wealth_process[i]['range'])),
graphic_opts=[
opts.GraphicGroup(
graphic_item=opts.GraphicItem(
rotation=JsCode("Math.PI / 4"),
bounding="raw",
right=100,
bottom=110,
z=100,
),
children=[
opts.GraphicRect(
graphic_item=opts.GraphicItem(
left="center", top="center", z=100
),
graphic_shape_opts=opts.GraphicShapeOpts(
width=400, height=50
),
graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
fill="rgba(0,0,0,0.3)"
),
),
opts.GraphicText(
graphic_item=opts.GraphicItem(
left="center", top="center", z=100
),
graphic_textstyle_opts=opts.GraphicTextStyleOpts(
text="第{}轮→马太效应".format(i),
font="bold 26px Microsoft YaHei",
graphic_basicstyle_opts=opts.GraphicBasicStyleOpts(
fill="#fff"
),
),
),
],
)
],
)
)
tl.add(bar, "第{}轮".format(i))
tl.render("timeline_bar_with_graphic.html")
tl.render_notebook()
热力图
示例
import random
from pyecharts import HeatMap
from pyecharts import options as opts
x_axis = [
"12a", "1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a",
"12p", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p"]
y_axis = [
"Saturday", "Friday", "Thursday", "Wednesday", "Tuesday", "Monday", "Sunday"]
data = [[i, j, random.randint(0, 50)] for i in range(24) for j in range(7)]
# ==== 旧版过程调用 =====
heatmap = HeatMap()
heatmap.add(
"热力图直角坐标系",
x_axis,
y_axis,
data,
is_visualmap=True,
visual_range=[0, 1], # 取值范围
visual_range_color=["#CDC5BF","#FF69B4", "#FF0000"], # 颜色设置
visual_text_color="#000",
visual_orient="horizontal",
)
heatmap.render('heatmap.html')
heatmap.render_notebook()
# === 新版链式调用 ===
from pyecharts.charts import HeatMap
heatmap = (HeatMap()
.add_xaxis(x_axis)
.add_yaxis("发博数", y_axis, data)
.set_global_opts(
title_opts=opts.TitleOpts(title="用户发博时间热力图"),
visualmap_opts=opts.VisualMapOpts(max_=600)
)
)
【2024-8-26】热力图实践
- 数据格式
[i,j,val]
, 其中 val 必须 int 类型
import numpy as np
from pyecharts.charts import HeatMap
from pyecharts import options as opts
class_list = [2,3,4,20,30,41,42,51,52,53]
str = """[[1219 0 0 12 74 31 0 0 0 0]
[ 6 0 0 0 3 1 0 0 0 0]
[ 14 0 0 9 8 0 0 0 0 0]
[ 12 0 0 97 19 0 0 0 0 0]
[ 119 0 0 14 91 16 0 0 0 0]
[ 22 0 0 4 21 77 0 0 0 0]
[ 0 0 0 0 0 1 0 0 0 0]
[ 9 0 0 1 3 1 0 0 0 0]
[ 1 0 0 0 1 0 0 0 0 0]
[ 2 0 0 2 0 0 0 0 0 0]]"""
# print(str.replace('\n', ';'))
confusion = np.matrix(str.replace('\n', ';'))
print(confusion)
# 数据格式: [i,j, val] -> [[0,0, 10], [0,1, 11]]
data_list = [[i,j, int(confusion[i,j])] for i in range(confusion.shape[0]) for j in range(confusion.shape[1])]
heatmap = (HeatMap()
.add_xaxis(class_list)
.add_yaxis("预测数目", class_list, data_list)
.set_global_opts(
title_opts=opts.TitleOpts(title="换query多分类混淆矩阵图"),
visualmap_opts=opts.VisualMapOpts(max_=confusion.max())
)
)
heatmap.render('换query多分类.html')
heatmap.render_notebook()
意图槽位图
【2021-8-22】实践,参考官方教程
# y轴标签 intent_list,x轴便签slot_list,数据矩阵data
data = [[x,y,intent_slot_list[y][x]] for x in range(len(slot_list)) for y in range(len(intent_list))]
heat_map = (
HeatMap(init_opts=opts.InitOpts(width="1440px", height="720px"))
.add_xaxis(xaxis_data=slot_list)
.add_yaxis(
series_name="频次",
yaxis_data=intent_list,
value=data,
label_opts=opts.LabelOpts(
is_show=True, color="#fff", position="bottom", horizontal_align="50%"
),
)
.set_series_opts()
.set_global_opts(
title_opts=opts.TitleOpts(title="意图槽位分布图"),
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
legend_opts=opts.LegendOpts(is_show=False),
xaxis_opts=opts.AxisOpts(
type_="category",
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
yaxis_opts=opts.AxisOpts(
type_="category",
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
visualmap_opts=opts.VisualMapOpts(
min_=1, max_=1000, is_calculable=True, orient="horizontal", pos_left="center"
),
)
)
多轮对话转化
import random
import pyecharts as pe
# 为了避免显示空白,加入以下代码执行后,重新刷新当前jupyter页面即可
pe.configure(
jshost="https://pyecharts.github.io/assets/js",
echarts_template_dir=None,
force_js_embed=None,
output_image=None,
global_theme=None
)
# 代码参考:http://pyecharts.org/#/zh-cn/charts_base?id=heatmap%EF%BC%88%E7%83%AD%E5%8A%9B%E5%9B%BE%EF%BC%89
# x_axis = ["12a", "1a", "2a", "3a", "4a", "5a", "6a", "7a", "8a", "9a", "10a", "11a",
# "12p", "1p", "2p", "3p", "4p", "5p", "6p", "7p", "8p", "9p", "10p", "11p"]
# y_axis = ["Saturday", "Friday", "Thursday", "Wednesday", "Tuesday", "Monday", "Sunday"]
# data = [[i, j, random.randint(0, 50)] for i in range(24) for j in range(7)]
page = pe.Page('多轮对话场景分析')
title = '投诉进度查询状态转化'
# (1) 节点状态转化图
x_axis = y_axis = attr_list
item_len = len(x_axis)
data = [[x_axis[i], y_axis[j], val_list[i][j]] for i in range(item_len) for j in range(item_len)]
heatmap = pe.HeatMap()
heatmap.add(
'%s(x -> y)'%(title),
x_axis,
y_axis,
data,
is_visualmap=True,
visual_range=[dh.get_values().min(), dh.get_values().max()],
visual_text_color="#000",
visual_orient="horizontal",
)
#heatmap.render()
page.add(heatmap)
水球图
代码
from pyecharts import options as opts
from pyecharts.charts import Liquid, Grid
from pyecharts.globals import SymbolType
c1 = (
Liquid()
.add("有效交互成功率", [0.75],
center=["15%", "50%"], # 多个图时,各自位置范围
is_outline_show=False, # 边框不显示
shape=SymbolType.RECT) # 水球形状(默认圆形,此处设置为矩形)
#.add("有效交互成功率", [his_data[-1][-2]*0.01], center=["15%", "50%"])
.set_global_opts(title_opts=opts.TitleOpts(title="比例值"))
#.render("liquid_base.html")
)
graph 图谱
参数说明
参数设置:
# 节点方法
class GraphNode(
# 数据项名称。
name: Optional[str] = None,
# 节点的初始 x 值。在不指定的时候需要指明layout属性选择布局方式。
x: Optional[Numeric] = None,
# 节点的初始 y 值。在不指定的时候需要指明layout属性选择布局方式。
y: Optional[Numeric] = None,
# 节点在力引导布局中是否固定。
is_fixed: bool = False,
# 数据项值。
value: Union[str, Sequence, None] = None,
# 数据项所在类目的 index。
category: Optional[int] = None,
# 该类目节点标记的图形。
# ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle',
# 'diamond', 'pin', 'arrow', 'none'
# 可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI。
symbol: Optional[str] = None,
# 该类目节点标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高,
# 例如 [20, 10] 表示标记宽为 20,高为 10。
symbol_size: Union[Numeric, Sequence, None] = None,
# 标签配置项,参考 `series_options.LabelOpts`
label_opts: Optional[LabelOpts] = None,
)
# 节点分类
class GraphCategory(
# 类目名称,用于和 legend 对应以及格式化 tooltip 的内容。
name: Optional[str] = None,
# 该类目节点标记的图形。
# ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle',
# 'diamond', 'pin', 'arrow', 'none'
# 可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI。
symbol: Optional[str] = None,
# 该类目节点标记的大小,可以设置成诸如 10 这样单一的数字,也可以用数组分开表示宽和高,
# 例如 [20, 10] 表示标记宽为 20,高为 10。
symbol_size: Union[Numeric, Sequence, None] = None,
# # 标签样式,参考 `series_options.LabelOpts`
label_opts: Optional[LabelOpts] = None,
)
# 边方法
class GraphLink(
# 边的源节点名称的字符串,也支持使用数字表示源节点的索引。
source: Union[str, int, None] = None,
# 边的目标节点名称的字符串,也支持使用数字表示源节点的索引。
target: Union[str, int, None] = None,
# 边的数值,可以在力引导布局中用于映射到边的长度。
value: Optional[Numeric] = None,
# 边两端的标记类型,可以是一个数组分别指定两端,也可以是单个统一指定。
symbol: Union[str, Sequence, None] = None,
# 边两端的标记大小,可以是一个数组分别指定两端,也可以是单个统一指定。
symbol_size: Union[Numeric, Sequence, None] = None,
# 关系边的线条样式,参考 `series_options.LineStyleOpts`
linestyle_opts: Optional[LineStyleOpts] = None,
# 标签样式,参考 `series_options.LabelOpts`
label_opts: Optional[LabelOpts] = None,
)
# add方法
def add(
# 系列名称,用于 tooltip 的显示,legend 的图例筛选。
series_name: str,
# 关系图节点数据项列表,参考 `opts.GraphNode`
nodes: Sequence[Union[opts.GraphNode, dict]],
# 关系图节点间关系数据项列表,参考 `opts.GraphLink`
links: Sequence[Union[opts.GraphLink, dict]],
# 关系图节点分类的类目列表,参考 `opts.GraphCategory`
categories: Union[Sequence[Union[opts.GraphCategory, dict]], None] = None,
# 是否选中图例。
is_selected: bool = True,
# 是否在鼠标移到节点上的时候突出显示节点以及节点的边和邻接节点。
is_focusnode: bool = True,
# 是否开启鼠标缩放和平移漫游。
is_roam: bool = True,
# 节点是否可拖拽,只在使用力引导布局的时候有用。
is_draggable: bool = False,
# 是否旋转标签,默认不旋转。
is_rotate_label: bool = False,
# ==== 图的布局 ====== 可选:
# 'none' 不采用任何布局,使用节点中提供的 x, y 作为节点的位置。
# 'circular' 采用环形布局。
# 'force' 采用力引导布局。
layout: str = "force",
# 关系图节点标记的图形。
# ECharts 提供的标记类型包括 'circle', 'rect', 'roundRect', 'triangle',
# 'diamond', 'pin', 'arrow', 'none'
# 可以通过 'image://url' 设置为图片,其中 URL 为图片的链接,或者 dataURI。
symbol: Optional[str] = None,
# 关系图节点标记的大小
# 可以设置成诸如 10 这样单一的数字
# 也可以用数组分开表示宽和高,例如 [20, 10] 表示标记宽为20,高为10。
symbol_size: types.Numeric = 10,
# 边的两个节点之间的距离,这个距离也会受 repulsion。
# 支持设置成数组表达边长的范围,此时不同大小的值会线性映射到不同的长度。值越小则长度越长。
edge_length: Numeric = 50,
# 节点受到的向中心的引力因子。该值越大节点越往中心点靠拢。
gravity: Numeric = 0.2,
# 节点之间的斥力因子。
# 支持设置成数组表达斥力的范围,此时不同大小的值会线性映射到不同的斥力。值越大则斥力越大
repulsion: Numeric = 50,
# Graph 图节点边的 Label 配置(即在边上显示数据或标注的配置)
edge_label: types.Label = None,
# 边两端的标记类型,可以是一个数组分别指定两端,也可以是单个统一指定。
# 默认不显示标记,常见的可以设置为箭头,如下:edgeSymbol: ['circle', 'arrow']
edge_symbol: Optional[str] = None,
# 边两端的标记大小,可以是一个数组分别指定两端,也可以是单个统一指定。
edge_symbol_size: Numeric = 10,
# 标签配置项,参考 `series_options.LabelOpts`
label_opts: Union[opts.LabelOpts, dict] = opts.LabelOpts(),
# 关系边的公用线条样式。
linestyle_opts: Union[opts.LineStyleOpts, dict] = opts.LineStyleOpts(),
# 提示框组件配置项,参考 `series_options.TooltipOpts`
tooltip_opts: Union[opts.TooltipOpts, dict, None] = None,
# 图元样式配置项,参考 `series_options.ItemStyleOpts`
itemstyle_opts: Union[opts.ItemStyleOpts, dict, None] = None,
)
(1) Graph 绘制
【2024-7-6】设置节点、边,绘图即可,实测通过
- pyecharts 2.0.6
#!pip install pyecharts
from pyecharts import options as opts
from pyecharts.charts import Graph
# 边信息(附加数值)
# 注意: 起点终点一样的节点,边无法绘制
data_info = [
('甲', '乙', '1', 'Blue'),
('甲', '丙', '2', 'Green'),
('甲', '丁', '3', 'Yellow'),
('乙', '丁', '1', 'Blue'),
('乙', '乙', '2', 'Green'),
('乙', '庚', '3', 'Yellow'),
('丙', '庚', '5', 'Red'),
('丙', '壬', '1', 'Blue')]
# 提取全部节点
node_list = set([i[0] for i in data_info]) | set([i[1] for i in data_info])
# 设置节点信息
nodes = []
for i in node_list:
nodes.append(opts.GraphNode(
name=i,
symbol_size=50,
label_opts=opts.LabelOpts(is_show=True, color='white'))
# label_opts=opts.LabelOpts(is_show=True, font_size='20', color='white'))
)
# 设置边信息
links = []
for i in data_info:
links.append(
opts.GraphLink(
source=i[0],
target=i[1],
value=int(i[2]),
linestyle_opts=opts.LineStyleOpts(
color=i[3].lower(),
width=2*int(i[2]),
opacity=0.5)
)
)
# 开始绘图
c = (
Graph(init_opts=opts.InitOpts(width="1440px", height="720px", bg_color="#000000"))
.add("", nodes, links, repulsion=400,
symbol_size= [0, 20],edge_symbol =['circle', 'arrow'], is_draggable=True,
is_rotate_label=True, # 标签旋转
linestyle_opts=opts.LineStyleOpts(color="source", type_= 'dashed'),#'solid', 'dashed', 'dotted'
label_opts=opts.LabelOpts(is_show=True, font_size='18', color='green'), # 节点label
edge_label=opts.LabelOpts(is_show=True, position="middle", # 边label
font_size='15', formatter="{c}") # {b} 是默认值:a>b
)
.set_global_opts(title_opts=opts.TitleOpts(title="状态图"),
legend_opts=opts.LegendOpts(pos_top="5%",pos_right="15%", orient='vertical')
)
)
c.render('可视化.html')
c.render_notebook()
(2) Graph 图谱
【2023-12-4】 notebook 6.1.5 上实现通过,高版本会出现白屏,详见jupyter问题
配置数据类型
data:[
{
name:'节点名称',
value:'节点值'
x:节点坐标, 在不指定的时候需要指明layout属性选择布局方式。
y:节点坐标,
symbolSize: 80,
draggable: true, 节点是否可拖拽,只在使用力引导布局的时候有用。
itemStyle: {},
categrory:'在categories中设置的名称,用于图例等分类' 或者数值索引
}
pip install notebook==6.1.5
【2020-11-27】多轮转化图
【2024-7-6】实测通过
- pyecharts 2.0.6
代码
# (2) Graph图谱
from pyecharts import Graph
# 定义节点
categories=[{}, {'name': '类目1'},{'name': '类目2'}] # 节点类型
nodes = [{"name": "A", "symbolSize": 10, "category":2},
{"name": "B", "symbolSize": 20, "category":2},
{"name": "C", "symbolSize": 30, "category":1},
{"name": "D", "symbolSize": 40, "category":2},
{"name": "E", "symbolSize": 50, "category":1},
{"name": "F", "symbolSize": 40, "category":2},
# opts.GraphNode(name="所有交互", symbol_size=50, x=500, y=200), # 节点位置固定,与add里的layout='none'配合使用才生效
{ "name": "所有交互", "symbol_size": 50, "x":500, "y":200, "category":2}, # 节点位置固定,与add里的layout='none'配合使用才生效
{"name": "G", "symbolSize": 30, "category":1},
{"name": "H", "symbolSize": 20, "category":2}]
# 定义边/链接
links = []
for i in nodes:
for j in nodes:
links.append({"source": i.get('name'), "target": j.get('name')})
nodes = json.loads(json.dumps(nodes))
# 图表
graph = Graph("%s-状态图"%(title))
# 添加节点/边
graph.add("", nodes, links, repulsion=80000, symbol='roundRect',
layout='force', # layout=none固定节点位置
# edgeSymbolSize= [0, 20], categories=categories,
is_rotate_label=True, # 标签旋转
# formatter="{b},数值为{c} ", # js显示数据格式,可用参数{a},{b},...,{e}
linestyle_opts=opts.LineStyleOpts(color="source", curve=0.3), # 线型设置,curve=0.3表示弯曲程度
#edgeSymbol =['circle', 'arrow']
)
# 集中渲染到html文件
graph.render('muti_turn_vis.html')
(3) 自定义
签约大屏转化漏斗
# (3) 自定义绘图 【2021-10-23】
from pyecharts import options as opts
from pyecharts.charts import Page, Tab
from pyecharts.charts import Graph
dt_info = '2021-10-23'
# 节点类型
categories=[{}, {'name': '所有交互'},{'name': '无效交互'},{'name': '有效交互'},{'name': '成功'},{'name': '失败'}]
# 边信息
trans_info = {'所有交互->有效交互': 120,
'所有交互->无效交互': 189,
'无效交互->环境杂音': 186,
'无效交互->教学': 3,
'有效交互->成功': 115,
'有效交互->失败': 1,
'失败->ASR错误': 1,
'失败->新意图': 3,
'失败->重复唤醒': 1,
'失败->NLU泛化': 0,
'成功->退出': 77,
'成功->签约意图': 33,
'成功->闲聊': 3,
'成功->其它': 2}
# 节点信息
nodes = [
#opts.GraphNode(name="所有交互", symbol_size=50), # 节点位置不定
opts.GraphNode(name=f"所有交互\n{1000}", symbol_size=50, x=500, y=220, category=1, value=1000,
label_opts=opts.LabelOpts(is_show=True, font_size='20', color='green') # 可以单独设置label格式
), # 节点位置固定,与add里的layout='none'配合使用才生效
opts.GraphNode(name="无效交互", symbol_size=50, x=450, y=250, category=2, value=trans_info["所有交互->无效交互"]),
opts.GraphNode(name="有效交互", symbol_size=50, x=550, y=250, category=3, value=trans_info["所有交互->有效交互"]),
opts.GraphNode(name="失败", symbol_size=50, x=520, y=280, category=5, value=trans_info["有效交互->失败"]),
opts.GraphNode(name="成功", symbol_size=50, x=580, y=280, category=4, value=trans_info["有效交互->成功"]),
opts.GraphNode(name="环境杂音", symbol_size=30, x=380, y=310, category=2, value=trans_info["无效交互->环境杂音"]),
opts.GraphNode(name="教学", symbol_size=30, x=400, y=310, category=2, value=trans_info["无效交互->教学"]),
opts.GraphNode(name="退出", symbol_size=30, x=550, y=310, category=4, value=trans_info["成功->退出"]),
opts.GraphNode(name="闲聊", symbol_size=30, x=570, y=310, category=4, value=trans_info["成功->闲聊"]),
opts.GraphNode(name="签约意图", symbol_size=30, x=590, y=310, category=4, value=trans_info["成功->签约意图"]),
opts.GraphNode(name="其它", symbol_size=30, x=610, y=310, category=4, value=trans_info["成功->其它"]),
opts.GraphNode(name="重复唤醒", symbol_size=30, x=480, y=310, category=5, value=trans_info["失败->重复唤醒"]),
opts.GraphNode(name="ASR错误", symbol_size=30, x=500, y=310, category=5, value=trans_info["失败->ASR错误"]),
opts.GraphNode(name="NLU泛化", symbol_size=30, x=520, y=310, category=5, value=trans_info["失败->NLU泛化"]),
opts.GraphNode(name="新意图", symbol_size=30, x=540, y=310, category=5, value=trans_info["失败->新意图"]),
]
# 【2021-11-2】 由于节点无法显示数值,只好在节点名中包含数值,这会影响边关联,所以需要单独获取node对象的名称
# node.get('name') 获取节点名
nodes_name_dict = dict([[i.get('name').split('\n')[0], i.get('name')] for i in nodes])
# 逐个添加边(可忽略)
links = [
opts.GraphLink(source="所有交互", target="无效交互", linestyle_opts=opts.LineStyleOpts(width=20, opacity=0.5)),
opts.GraphLink(source="所有交互", target="有效交互", linestyle_opts=opts.LineStyleOpts(width=4, opacity=0.5)),
opts.GraphLink(source="无效交互", target="环境杂音"),
opts.GraphLink(source="无效交互", target="教学"),
opts.GraphLink(source="有效交互", target="失败"),
opts.GraphLink(source="有效交互", target="成功"),
opts.GraphLink(source="失败", target="重复唤醒"),
opts.GraphLink(source="失败", target="ASR错误"),
opts.GraphLink(source="失败", target="NLU泛化"),
opts.GraphLink(source="失败", target="新意图"),
opts.GraphLink(source="成功", target="退出"),
opts.GraphLink(source="成功", target="闲聊"),
opts.GraphLink(source="成功", target="签约意图"),
opts.GraphLink(source="成功", target="其它"),
]
# 或批量添加(提前准备trans_info字典)
links = []
for item in trans_info:
s, d = item.split('->')
width = max(int(trans_info[item]*30/200), 1)
links.append(opts.GraphLink(source=s, target=d,
# source=nodes_name_dict.get(s, f'异常-{s}'),
# target=nodes_name_dict.get(d, f'异常-{d}'),
value=round(trans_info[item]*100/1000,2),
linestyle_opts=opts.LineStyleOpts(width=width, opacity=0.3)))
# 绘图
c = (
Graph(init_opts=opts.InitOpts(width="1440px", height="720px"))
.add("", nodes, links, repulsion=400, symbol='roundRect', layout='none', # force
symbol_size= [0, 20],edge_symbol =['circle', 'arrow'], is_draggable=True, categories=categories,
is_rotate_label=True, # 标签旋转
linestyle_opts=opts.LineStyleOpts(color="source", type_= 'dashed'),#'solid', 'dashed', 'dotted'
label_opts=opts.LabelOpts(is_show=True, font_size='18', color='blue'), # 节点label
edge_label=opts.LabelOpts(is_show=True, position="middle", # 边label
font_size='15', formatter="{c}%") # {b} 是默认值:a>b
)
.set_global_opts(title_opts=opts.TitleOpts(title="签约大屏漏斗数据"),
legend_opts=opts.LegendOpts(pos_top="5%",pos_right="15%", orient='vertical')
)
#.render("graph_with_options.html")
)
# make_snapshot(driver,g.render("gauge.html"),"gauge.png")
tab = Tab()
tab.add(c, '交互漏斗图')
tab.render(f'可视化-签约大屏城市流量分布{dt_info}.html')
tab.render_notebook()
(4)Mathematica
【2024-7-6】 wolfram 推出的数学软件 Mathematica 直接绘制3D可视化图
- 官方示例:Graph3D
散点图
2D散点图
带动画效果:Effectscatter
from pyecharts import options as opts
from pyecharts.charts import EffectScatter
from pyecharts.faker import Faker
c = (
EffectScatter()
.add_xaxis(Faker.choose())
.add_yaxis("", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="EffectScatter-基本示例"))
.render("effectscatter_base.html")
)
3D散点图
散点图维度绘制时,注意数轴类型,默认只把Z轴当数值,其余轴当做离散类目处理,因此会出现x、y轴数值失效的情形,此时需要单独设置x和y轴的类型。
- 注意:【2021-8-19】2D和3D设置方法不同!
- 参考:全局配置项( VisualMapOpts 视觉映射配置项)
代码:适用于1.*以上版本
import random
from pyecharts import options as opts
#from pyecharts.charts import Scatter # 2D散点图
from pyecharts.charts import Scatter3D
from pyecharts.faker import Faker
N = 50
label = range(N)
# 数据点格式:[x,y,z,label],默认取前面数据当坐标,后面作为其他信息
Scatter_data = [(random.randint(0,N),random.randint(0,N),random.randint(0,N)) for i in range(N)]
c = (
Scatter3D(init_opts = opts.InitOpts(width='900px',height='600px')) #初始化
.add("",Scatter_data,
xaxis3d_opts=opts.Axis3DOpts(type_='value'), # 3D散点图x轴类型设置
yaxis3d_opts=opts.Axis3DOpts(type_='value'), # 3D散点图y轴类型设置
#grid3d_opts=opts.Grid3DOpts(width=100, depth=100, rotate_speed=100, is_rotate=True) # 自动旋转
)
#设置全局配置项
.set_global_opts(
title_opts=opts.TitleOpts(title="3D散点图"), #添加标题
visualmap_opts=opts.VisualMapOpts(
#type_ = 'color', # 或 'size', 映射维度:颜色或大小
is_show = True, # 是否显示视觉映射配置
item_width = 0,# 图形的宽度,即长条的宽度。
item_height = 0,# 图形的高度,即长条的高度。
background_color = '#CCCC33',# visualMap 组件的背景色。
border_color = '#EE1111',# visualMap 组件的边框颜色。
is_calculable = True,# 是否显示拖拽用的手柄(手柄能拖拽调整选中范围)。
pos_left = 'center', # 如果 left 的值为'left', 'center', 'right',组件会根据相应的位置自动对齐。
pos_right = None,
pos_top = None,
pos_bottom = None,
border_width = 2,# visualMap 边框线宽,单位px。
orient = 'horizontal',# 如何放置 visualMap 组件,水平('horizontal')或者竖直('vertical')。
min_=0, # visualMapPiecewise 组件的最小值
max_=50, # visualMapPiecewise 组件的最大值
pos_top=50, # visualMap 组件离容器上侧的距离
range_opacity = None,# visualMap 图元以及其附属物(如文字标签)的透明度。range_opacity: Optional[Numeric] = None,
dimension=2, # 组件映射维度, 如2表示按第三(2+1)个维度取值范围来标颜色
range_text = ['高', '低'], # 两端的文本,如['High', 'Low'],(自定义) range_text: Union[list, tuple] = None,
range_size=[10, 40], # 数据点大小
range_color=Faker.visual_color, #颜色映射
#range_color=["#0b9df0","#00fea8","#00ff0d","#f5f811","#f09a09","#fe0300","#1710c0",] #颜色映射
split_number = 5, # 对于连续型数据,自动平均切分成几段。默认为5段。连续数据的范围需要 max 和 min 来指定
# 图例区间、数值范围自定义, is_piecewise和pieces配合使用
#is_piecewise=True,
pieces=[
{"max": 1499, "min": 1200, "label": ">=1200", "color": "#B40404"},
{"max": 1199, "min": 900, "label": "900-1199", "color": "#DF0101"},
{"max": 899, "min": 600, "label": "600-899", "color": "#F78181"},
{"max": 599, "min": 300, "label": "300-599", "color": "#F5A9A9"},
{"max": 299, "min": 0, "label": "0-299", "color": "#FFFFCC"},
],
# 文字样式配置项,参考 `series_options.TextStyleOpts`
textstyle_opts = None,
),
#xaxis_opts=opts.AxisOpts(type_='value'), # 2D散点图设置数值
#yaxis_opts=opts.AxisOpts(type_='value'),# 2D散点图设置数值
#zaxis_opts=opts.AxisOpts(type_='value') # category
)
)
c.render("3D散点图.html") # 保存到文件
c.render_notebook() # 输出到jupyter notebook页面
效果示例:
【2021-11-11】3D散点图可视化问题:颜色设置,echarts散点图标注颜色设置不起作用?
- 原因:visualMap 组件控制了 series 中的数据,进行了『视觉编码』,也就是将数据映射到视觉元素(视觉通道)。所以,data中value的值不同,映射后的颜色会改变。
- 解决:想哪个数据不被控制,就要设置它的visualMap:false
visualMap: {
show:false,
min: 0,
max: 100,
splitNumber: 5,
inRange: {
color: ['#d94e5d','#eac736','#50a3ba'].reverse()
},
textStyle: {
color: '#fff'
}
},
series: [
{},//地图,这里省略
{
type:'effectScatter',
coordinateSystem: 'geo',
symbol:'pin',
symbolSize:15,
rippleEffect: {
brushType: 'stroke'
},
itemStyle:{
color:'red'
},
// data:[[113.65, 35.76,0]] 颜色是浅蓝色
// data:[{value:[113.65, 35.76,0],itemStyle : {normal : {color :'red'}}}] 不起作用
//data:[[113.65, 35.76,100]] //这么写颜色虽然变红了,但不是正宗的红色
data:[{value:[113.65, 35.76,0],visualMap: false}] //这样写对了
}]
【2021-11-11】使用pyecharts绘制三维散点图,根据类别使用不同颜色区分数据
自定义点的颜色:聚类结果显示中,需要用颜色区分不同类别
- 以下代码适用于最新的pyecharts版本,但是生成的效果却无法达到预期目标。具体情况是三个类别的点不在同一个坐标系中!(可以通过坐标轴的数值来判断)
- pyecharts==0.5的版本最符合我的要求, visualmap的文字没有显示是因为颜色问题,可以加上限制
- visual_text_color=”#000”
def plot_scatter(X, Y, save_dir): #version 1.5-1.9
from pyecharts.charts import Scatter3D, Page
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from pyecharts.render import make_snapshot
from snapshot_selenium import snapshot
Y = np.expand_dims(Y, 1)
data = np.concatenate((X,Y),axis=1)
piece=[
{'value': 0,'label': 'class A','color':'#e57c27'},
{'value': 1, 'label': 'class B','color':'#72a93f'},
{'value': 2, 'label': 'class C','color':'#368dc4'}
]
sc1 = Scatter3D()
sc1.add("", data.tolist())
sc1.set_global_opts(title_opts=opts.TitleOpts(title="3D scatter"),
visualmap_opts=opts.VisualMapOpts(dimension=3,is_piecewise=True, pieces=piece))
sc1.render(save_dir+'/test.html')
make_snapshot(snapshot, sc1.render(), save_dir+'/test.png')
数学函数图
import math
from typing import Union
import pyecharts.options as opts
from pyecharts.charts import Surface3D
"""
Gallery 使用 pyecharts 1.1.0
参考地址: https://echarts.apache.org/examples/editor.html?c=surface-wave&gl=1
目前无法实现的功能:
1、暂时无法设置光滑表面 wireframe
2、暂时无法把 visualmap 进行隐藏
"""
def float_range(start: int, end: int, step: Union[int, float], round_number: int = 2):
"""
浮点数 range
:param start: 起始值
:param end: 结束值
:param step: 步长
:param round_number: 精度
:return: 返回一个 list
"""
temp = []
while True:
if start < end:
temp.append(round(start, round_number))
start += step
else:
break
return temp
def surface3d_data():
for t0 in float_range(-3, 3, 0.05):
y = t0
for t1 in float_range(-3, 3, 0.05):
x = t1
z = math.sin(x ** 2 + y ** 2) * x / 3.14
yield [x, y, z]
(
Surface3D(init_opts=opts.InitOpts(width="1600px", height="800px"))
.add(
series_name="",
shading="color",
data=list(surface3d_data()),
xaxis3d_opts=opts.Axis3DOpts(type_="value"),
yaxis3d_opts=opts.Axis3DOpts(type_="value"),
grid3d_opts=opts.Grid3DOpts(width=100, height=40, depth=100),
)
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(
dimension=2,
max_=1,
min_=-1,
range_color=[
"#313695",
"#4575b4",
"#74add1",
"#abd9e9",
"#e0f3f8",
"#ffffbf",
"#fee090",
"#fdae61",
"#f46d43",
"#d73027",
"#a50026",
],
)
)
.render("surface_wave.html")
)
雷达图
雷达图
(Radar Chart),或称为戴布拉图
、蜘蛛网图
。参考
- 图形以一点为中心,每一变量维度为一极坐标轴,n个维度即形成n轴的由内向外放射状图形,形似蜘蛛网。
图形的基本构成如下:
- 数据点
- 雷达链
- 特征标签
- 半径轴
- 覆盖域
雷达图的应用特点:
- ① 同样是属于比较与分布类型,雷达图与柱状图最明显的差异
柱状图
在实际场景中通常被用于进行单(多)维度定性数据的可视化,比如一次期中考试,绘制柱状图来对比八个班级的语文平均分;- 而
雷达图
常常用于单(多)个体的多维度数据对比,进而呈现并帮助分析对象的优劣处,比如在这次考试中,绘制雷达图来观察二班的语文、数学、英语、生物、化学、物理科目平均分的优良分布。
- ② 如果遇到多总体,可以使用多幅雷达图,或者单幅雷达图中多层数据线的形式进行总体间对比。
- ③ 无论是变量特征还是对象总体都不要太多,前者(>10)会使得图像的轴过多,包含信息量过大而弱化了可读性,一眼看去让人感觉很复杂。后者(>5)要么会使得线条交叉密集,要么就是多重覆盖域因附着不同填充色而导致的信息覆盖问题,当然,如果每个总体都是单维突出类型,信息突出效果还是很好的。
- ④ 雷达图使用的数据是多特征的,会出现一种很常见的情况,比如年龄和收入的量纲或者说取值范围是不一致的。因为雷达图是维度内的粗略对比,我们并不会去根据图形计算一班和二班的数学平均分差究竟是多少,只需要得到二班在这次期中考试中数学比一班考得好的结论就可以,所以为了将各维度数据在一个取值范围内,我们在绘图前会考虑将数据归一化或者标准化。
- ⑤ 在应用场景上,通常有财务状况综合评价、用户画像、员工评分、医疗症状自评等等
add_schema
负责雷达图的设置:图解
- ①
schema
:指定雷达图的特征标签,每个轴的最大最小取值(方便画点),此前我们已经生成了取值范围的scope【{}】型,直接赋值就行。 - ② shape、center、radius :
- shape即雷达图的外轮廓形状,circle圆形为默认值。
- center为中心的位置,[50%,50%]指的是画布宽50%和高50%的位置,默认画布的宽高数据是900px*500px。。
- radius是雷达图外圆的半径长度,60%指的是当前画布的宽度和高度中较小者的60%。
- ③ AngleAxisOpts :角度坐标选项设置
- min_,max_ 指定角度范围。
- is_clockwise=False 角度递增的方向是否按照时钟转动(顺时针)的方向。
- interval 径向轴显示的间隔区间大小值,interval=10表示每隔10°划分径向轴角度。
- ④ RadiusAxisOpts :径向轴选项设置
- min_,max_ 同理,设置径向轴的取值范围。
- interval 用于径向轴上的划分,interval = 5 表示每隔 5 划分径向轴长度。
- SplitAreaOpts 用来设置我们的间隔区域,is_show=True才会有灰白相间的效果,opacity指的是不透明度,可以取[0,1] , 数值越大颜色越深。
- ⑤ PolarOpts : 极坐标的设置,我们选择默认值。
- ⑥ splitline_opt :如果设置为True,增加分割线,变化如下图所示(不显示雷达链,免得遮挡)
绘制雷达链
add()用于一条一条自定义绘制总体的雷达链。
- series_name :数据序列的名称,即总体名称。在静态图中它不会显示,交互过程中可以看到(如上上图)。
- data :对应总体的数据list,格式为
[{'name':'XX','value':[num,num,num]}]
,具体参考数据结构。这里需要注意的是,value的长度要和特征维度数一致。 - areastyle_opts :覆盖域的透明度设置,因为我们这里是五总体,必须要调整填充色的透明度。
- linestyle_opts : 雷达链的线条宽度设置
- color :指定不同总体雷达图的颜色,这里可以保证边界和内部填充色一致,而饱和度不同。
- symbol :设置数据点的形状,默认是空心圆。如果我们以许一的雷达链举例,数据点的形状改为三角形,即在color后面增加symbol = SymbolType.TRIANGLE,得到的结果如下
set_series_opts
- 用于设置数据序列的显示,只提LabelOpts,对数据序列数值标签的设置,默认is_show是True,多总体情况下数字标签多容易显得很混乱,影响视觉观感。
打分信息可视化
from pyecharts import options as opts
from pyecharts.charts import Radar
# [2023-6-5] 注意:每组数据不是简单的list,而是一个元素(数据向量)的数组!
v1 = [(4300, 10000, 28000, 35000, 50000, 19000)]
v2 = [(5000, 14000, 28000, 31000, 42000, 21000)]
p = Radar().add_schema(
schema=[
opts.RadarIndicatorItem(name="销售", max_=6500),
opts.RadarIndicatorItem(name="管理", max_=16000),
opts.RadarIndicatorItem(name="信息技术", max_=30000),
opts.RadarIndicatorItem(name="客服", max_=38000),
opts.RadarIndicatorItem(name="研发", max_=52000),
opts.RadarIndicatorItem(name="市场", max_=25000),
]
) \
.add("预算分配", v1)\
.add("实际开销", v2)\
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
p.render('radar.html')
p.render_notebook()
应用
- 效果图:img
# ------- 数据准备 -------
import pandas as pd
data = pd.DataFrame(pd.read_excel('案例数据.xlsx'))
# 生成绘图series
data_radar = []
for row in range(data.shape[0]):
dic = {}
value = []
for col in range(1,data.shape[1]):
value.append(int(data.iloc[row,col]))
dic['name'],dic['value'] = data['员工'][row],value
data_radar.append([dic])
# 各特征维度取值范围
scope = []
for col in range(1,data.shape[1]):
dic = {}
dic['name'] = data.columns[col]
dic['max'],dic['min'] = max(data.iloc[:,col]),0
scope.append(dic)
data_radar = [
[{'name':'许一','value':[22,3,3,7,3,5]}],
[{'name':'刘二','value':[27,2,4,10,4,3]}],
[{'name':'张三','value':[30,3,2,5,3,4]}],
[{'name':'李四','value':[24,5,2,7,3,3]}],
[{'name':'王五','value':[26,4,5,8,4,1]}]
]
# --------------------
from pyecharts import options as opts
from pyecharts.charts import Radar
from pyecharts.commons.utils import JsCode
c = (
# Radar()
Radar(init_opts=opts.InitOpts(bg_color={"type": "pattern", "image": JsCode("img"), "repeat": "no-repeat"})) # 加背景图
.add_js_funcs( """ var img = new Image();
img.src = '背景.jpg'; """)
.add_schema(
schema=scope,
shape="circle",
center=["50%", "50%"],#宽高:900px*500px
radius="60%",
angleaxis_opts=opts.AngleAxisOpts(
min_=0,
max_=360,
is_clockwise=False,
interval=10,
axistick_opts=opts.AxisTickOpts(is_show=True),
axislabel_opts=opts.LabelOpts(is_show=True),
axisline_opts=opts.AxisLineOpts(is_show=True),
splitline_opts=opts.SplitLineOpts(is_show=True)
),
radiusaxis_opts=opts.RadiusAxisOpts(
min_=0,
max_=30,
interval=5,
splitarea_opts=opts.SplitAreaOpts(
is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1)
),
),
polar_opts=opts.PolarOpts(),
splitline_opt=opts.SplitLineOpts(is_show=False)
)
.add(
series_name="许一",
data=data_radar[0],
areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
linestyle_opts=opts.LineStyleOpts(width=2),
color='#fc5a50'
)
.add(
series_name="刘二",
data=data_radar[1],
areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
linestyle_opts=opts.LineStyleOpts(width=2),
color='#35ad6b'
)
.add(
series_name="张三",
data=data_radar[2],
areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
linestyle_opts=opts.LineStyleOpts(width=2),
color='#3d7afd'
)
.add(
series_name="李四",
data=data_radar[3],
areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
linestyle_opts=opts.LineStyleOpts(width=2),
color='#aa23ff'
)
.add(
series_name="王五",
data=data_radar[4],
areastyle_opts=opts.AreaStyleOpts(opacity=0.2),
linestyle_opts=opts.LineStyleOpts(width=2),
color='#fcb001'
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title = '员工评价',subtitle = '林老头ss',pos_left='left'))
.render("雷达图示例.html")
)
import pyecharts as pe
# score分值是嵌套数组!
s = {'score':[[]], 'name_cn':[], 'full_score':[]}
for i in data['factor_score']:
s['score'][0].append(i['score'])
s['name_cn'].append(i['name_cn'])
s['full_score'].append(i['ref_score']['full_score'])
print(s)
print(data['total_score']['score'])
print([(s['name_cn'][i],s['full_score'][i],s['score'][i]) for i in range(len(s['score']))])
c = pe.charts.Radar()
opt = pe.options
c.add_schema(
#schema= [ opt.RadarIndicatorItem(name=s['name_cn'][i], max_=s['full_score'][i]) for i in range(len(s['score']))]
schema = [
opt.RadarIndicatorItem(name=s['name_cn'][0], max_=s['full_score'][0]),
opt.RadarIndicatorItem(name=s['name_cn'][1], max_=s['full_score'][1]),
opt.RadarIndicatorItem(name=s['name_cn'][2], max_=s['full_score'][2]),
opt.RadarIndicatorItem(name=s['name_cn'][3], max_=s['full_score'][3]),
opt.RadarIndicatorItem(name=s['name_cn'][4], max_=s['full_score'][4]),
opt.RadarIndicatorItem(name=s['name_cn'][5], max_=s['full_score'][5]),
opt.RadarIndicatorItem(name=s['name_cn'][6], max_=s['full_score'][6]),
opt.RadarIndicatorItem(name=s['name_cn'][7], max_=s['full_score'][7]),
]
).add("评分你好", s['score']) \
.set_series_opts(label_opts=pe.options.LabelOpts(is_show=True))
#.add("预算分配", v1).add("实际开销", v2) \
c.render('radar.html')
c.render_notebook()
地图数据
pyecharts有地理有几类:
- (1)Geo:地理坐标可视化,点形式
- (2)Map:矢量图形式,分成2D和3D
- (3)BMap:百度地图形式
基础数据:
- 全球国家地图: echarts-countries-pypkg :世界地图和 213 个国家,包括中国地图
- 中国省级地图: echarts-china-provinces-pypkg :23 个省,5 个自治区
- 中国市级地图: echarts-china-cities-pypkg :370 个中国城市
- 中国县区级地图: echarts-china-counties-pypkg :2882 个中国县、区
- 中国区域地图: echarts-china-misc-pypkg :11 个中国区域地图,比如华南、华北。
安装:
pip install echarts-countries-pypkg
pip install echarts-china-provinces-pypkg
pip install echarts-china-cities-pypkg
pip install echarts-china-counties-pypkg
pip install echarts-china-misc-pypkg
【2021-8-31】中国地理行政区划数据:省份、城市、区划数据,json格式:
!wget https://github.com/nixing87/area/blob/main/json/all_province_with_adcode_key.json
!wget https://github.com/nixing87/area/blob/main/json/all_city_with_adcode_key.json
- 各省份信息
省份 简称 省会 东经 北纬
安徽 皖 合肥 117.194778,31.86577
北京 京 116.403694,39.949459
重庆 渝 116.403694,39.949459
福建 闽 福州 119.292069,26.144144
甘肃 甘 兰州 103.856737,36.094212
广东 粤 广州 113.239359,23.185545
广西 桂 南宁 108.345678,22.861984
贵州 黔 贵阳 106.616332,26.707352
海南 琼 海口 110.350983,19.968035
河北 冀 石家庄 114.508772,38.083783
河南 豫 郑州 113.644099,34.769161
黑龙江 黑 哈尔滨 126.522207,45.801617
湖北 鄂 武汉 114.361594,30.601078
湖南 湘 长沙 112.926605,28.217167
吉林 吉 长春 125.326383,43.797768
江苏 苏 南京 118.832137,32.038322
江西 赣 南昌 115.851775,28.672488
辽宁 辽 沈阳 123.486653,41.682522
内蒙古 蒙 呼和浩特 111.785972,40.849642
宁夏 宁 银川 106.257585,38.482579
青海 青 西宁 101.851432,36.622494
山东 鲁 济南 117.194778,36.652148
山西 晋 太原 112.595453,37.858034
陕西 陕 西安 109.026378,34.350591
上海 沪 121.518142,31.211845
四川 川 成都 104.132697,30.561282
天津 津 117.286764,39.001295
西藏 藏 拉萨 91.144205,29.649484
新疆 新 乌鲁木齐 87.667116,43.817754
云南 滇 昆明 102.881681,24.866897
浙江 浙 杭州 120.211934,30.274265
香港 港 114.242011,22.272474
澳门 澳 113.579709,22.169692
台湾 台 台北 121.591732,25.034634
省份数据抽取
【2021-10-21】cpca库用于提取简体中文字符串中省/市/区信息并能够进行映射,检验和简单绘图的python模块。简单来说就是文本出现的市区名称转换为省份名称。
- pip install cpca
#!pip install cpca
# cpca是chinese province city area的缩写
# https://github.com/DQinYuan/chinese_province_city_area_mapper
location_str = ["徐汇区虹漕路461号58号楼5楼", "泉州市洛江区万安塘西工业区", "北京朝阳区北苑华贸城"]
import cpca
df = cpca.transform(location_str)
# 显示提取位置,大于-1的部分就代表提取的位置。-1则表明这个字段是靠程序推断出来的,或者没能提取出来。
#df = cpca.transform(location_str, pos_sensitive=True)
df
# 省 市 区 地址 adcode
# 0 上海市 上海市 徐汇区 虹漕路461号58号楼5楼 310104
# 1 福建省 泉州市 洛江区 万安塘西工业区 350504
# 2 北京市 市辖区 朝阳区 北苑华贸城 110105
# ------ 消歧 -------
cpca.transform(["朝阳区汉庭酒店大山子店"])
# 省 市 区 地址 adcode
#0 吉林省 长春市 朝阳区 汉庭酒店大山子店 220104
cpca.transform(["朝阳区汉庭酒店大山子店"],umap={"朝阳区":"110105"})
# 省 市 区 地址 adcode
#0 北京市 市辖区 朝阳区 汉庭酒店大山子店 110105
# ------- 长文本提取 --------
df = cpca.transform_text_with_addrs("分店位于徐汇区虹漕路461号58号楼5楼和泉州市洛江区万安塘西工业区以及南京鼓楼区")
# 自带的绘图工具 folium(速度慢),热力图显示
#pip install folium
from cpca import drawer
#df为上一段代码输出的df
drawer.draw_locations(df, "df.html")
# 改用echarts
#pip install pyecharts==0.5.11
#pip install echarts-countries-pypkg
#pip install pyecharts-snapshot
from cpca import drawer
drawer.echarts_draw(processed[cpca._ADCODE], "echarts.html")
drawer.echarts_cate_draw(processed[cpca._ADCODE], processed["省"], "echarts_cate.html")
平面地图
热力图形式, maptype
- 国家名:世界各国地图,如:瑞士
- china: 省
- china
# ---------- 世界地图(瑞士)--------
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.datasets import register_url
try:
register_url("https://echarts-maps.github.io/echarts-countries-js/")
except Exception:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
register_url("https://echarts-maps.github.io/echarts-countries-js/")
geo = (
Geo()
.add_schema(maptype="瑞士")
.set_global_opts(title_opts=opts.TitleOpts(title="瑞士"))
.render("geo_chart_countries_js.html")
)
# ---------- 中国各省份 --------
from pyecharts import options as opts
from pyecharts.charts import Geo # 地理坐标信息
from pyecharts.faker import Faker
from pyecharts.globals import ChartType # 图表类型
c = (
Geo()
.add_schema(maptype="china") # maptype=china(省),maptype="广东",maptype="海淀区"
.add(
"geo",
[list(z) for z in zip(Faker.provinces, Faker.values())],
# 图表类型,默认静态点
type_=ChartType.HEATMAP, # 这里设置为热力图
# type_=ChartType.EFFECT_SCATTER # 波纹点
label_opts=opts.LabelOpts(), # 显示省份名称
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(),
#visualmap_opts=opts.VisualMapOpts(is_piecewise=True), # 图例自动分段
title_opts=opts.TitleOpts(title="Geo-HeatMap"),
)
)
# ---------- 城市地图 --------
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker
table_data = [['北京市',10],['上海市',20]]
# table_data = [[k+'市', v] for (k,v) in city_info.items()]
tmp_data = [[i[0],i[1]] for i in table_data] # [[北京市,10],[上海市,20]]
m = (
Map(init_opts=opts.InitOpts(width="1440px", height="720px"))
.add("各城市热度", tmp_data, "china-cities",
label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
title_opts=opts.TitleOpts(title="各城市PV分布({dt_info})"),
visualmap_opts=opts.VisualMapOpts(max_=max([i[1] for i in tmp_data]), is_piecewise=True),
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
)
#.render("map_china_cities.html")
)
# ---------- 区地图 --------
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.datasets import register_url
try:
register_url("https://echarts-maps.github.io/echarts-china-counties-js/")
except Exception:
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
register_url("https://echarts-maps.github.io/echarts-china-counties-js/")
geo = (
Geo()
.add_schema(maptype="海淀区")
.set_global_opts(title_opts=opts.TitleOpts(title="海淀区"))
.render("geo_echart_china_js.html")
)
# ---------- 动态迁移图 --------
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.globals import ChartType, SymbolType
c = (
Geo()
.add_schema(maptype="china")
.add( # 城市数据
"",
[("广州", 55), ("北京", 66), ("杭州", 77), ("重庆", 88)],
type_=ChartType.EFFECT_SCATTER, # 点展示形式
color="white",
)
.add( # 迁移数据
"geo",
[("广州", "上海"), ("广州", "北京"), ("广州", "杭州"), ("广州", "重庆")],
type_=ChartType.LINES, # 箭头形式展示
effect_opts=opts.EffectOpts(
symbol=SymbolType.ARROW, symbol_size=6, color="blue"
),
linestyle_opts=opts.LineStyleOpts(curve=0.2),
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(title_opts=opts.TitleOpts(title="Geo-Lines"))
.render("geo_lines.html")
)
可视化案例
- Pyecharts绘制可视化地图专辑-星巴克门店分析
- 【2021-10-21】用Python带你看豆瓣上征婚交友的小姐姐们
- 分析:
- 豆瓣上居然还有一个叫我被豆油表白了的交友话题,阅读量居然高达 8087734 次,拥有 1000+ 篇话题,几乎每篇平均被阅读了 8000+ ,看了一下里面的小姐姐照片还挺多的。
- 华东和华南交友的小姐姐要比华北和西部的小姐姐多很多,看起来单身小姐姐都集中在一线城市及其周边。
- 代码
url_basic = 'https://m.douban.com/rexxar/api/v2/gallery/topic/18306/items?from_web=1&sort=hot&start={}&count=20&status_full_text=1&guest_only=0&ck=GStY'
headers = {
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9',
'Connection': 'keep-alive',
'Content-Type': 'application/x-www-form-urlencoded',
'Cookie': 'bid=n7vzKfXLoUA; douban-fav-remind=1; ll="108296"; __utmc=30149280; __utmz=30149280.1624276858.2.2.utmcsr=google|utmccn=(organic)|utmcmd=organic|utmctr=(not%20provided); ap_v=0,6.0; gr_user_id=ca8b9156-1926-4c82-9dda-27fc7f7ad51b; __utma=30149280.66080894.1623848440.1624276858.1624282580.3; __utmt=1; dbcl2="157316158:e4ojS8paSUc"; ck=GStY; push_doumail_num=0; __utmv=30149280.15731; frodotk="a187943e3a17e8bbe496bcbaae47ba31"; push_noty_num=0; __utmb=30149280.11.10.1624282580',
'Host': 'm.douban.com',
'Origin': 'https://www.douban.com',
'Referer': 'https://www.douban.com/gallery/topic/18306/',
'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
'sec-ch-ua-mobile': '?0',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36'
}
# 获取地理位置信息
for i in range(1,35):
res = requests.get(url=url_basic.format(i * 20), headers=headers)
res_json = json.loads(res.text)
index = 0
for item in res_json.get('items'):
target = item.get('target')
status = target.get('status')
print("这里是第 {} 个".format((i - 1) * 20 + index));
index = index + 1
with open('douban.txt', 'a+') as f:
f.write(json.dumps(status) + '\n');
sleeptime=random.randint(1, 10)
time.sleep(sleeptime)
# ---------- 下载图片信息 -----------
for line in file_object:
item = json.loads(line)
if item == None:
continue
images = item['images']
id = item['id']
index = 0
for i in images:
index = index + 1
url = i.get('large').get('url')
r = requests.get(url);
with open('./image/{}-{}.jpg'.format(id, index), 'wb') as f:
f.write(r.content)
# --------- 地图可视化 --------------
from pyecharts.charts import Geo
from pyecharts.globals import ChartType
addr_dic = {}
file_object = open('douban.txt','r')
try:
for line in file_object:
item = json.loads(line)
if item == None:
continue
author = item['author']
text = item['text']
addr_transform = cpca.transform([text])
addr = None
if addr_transform['省'].str.split(' ')[0] != None:
addr = addr_transform['省'].str.split(' ')[0][0].rstrip('省')
#这里提取创作者里面的地址
if addr is None and author['loc'] is not None:
cpca.transform([author['loc']['name']])
if addr_transform['省'].str.split(' ')[0] != None:
addr = addr_transform['省'].str.split(' ')[0][0].rstrip('省')
#这个地址要转换一下,不然 echarts 不认
if addr is not None:
if addr == '广西壮族自治区':
addr = '广西'
if addr == '香港特别行政区':
addr = '香港'
if addr == '澳门特别行政区':
addr = '澳门'
addr_dic[addr] = addr_dic.get(addr, 0) + 1
finally:
file_object.close()
# 小姐姐热力图
(
Geo()
.add_schema(maptype="china")
.add(
"",
[list(z) for z in zip(list(addr_dic.keys()), list(addr_dic.values()))],
type_=ChartType.HEATMAP,
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(),
).render("热力图.html")
)
二维显示
- 平面显示
【2023-1-4】数据加工: 直接根据字符串转城市数据
city_str = '''
上海 3449
苏州 1127
南京 1353
镇江 220
无锡 571
常州 447
徐州 166
盐城 186
南通 309
扬州 176
连云港 131
淮安 173
宿迁 64
泰州 122
大连 231
北京 642
石家庄 321
保定 251
邢台 39
邯郸 23
衡水 39
沈阳 580
通辽 47
天津 1629
唐山 193
秦皇岛 44
廊坊 185
沧州 35
哈尔滨 413
长春 525
深圳 720
广州 553
佛山 574
南宁 436
北海 86
桂林 124
贵港 38
柳州 114
海口 112
三亚 49
昆明 651
大理 33
贵阳 375
遵义 45
厦门 452
泉州 471
漳州 155
三明 41
南平 33
清远 139
惠州 453
东莞 435
河源 43
汕头 44
珠海 307
中山 258
肇庆 112
湛江 283
茂名 128
江门 97
阳江 21
烟台 184
青岛 965
威海 204
潍坊 162
临沂 159
济南 796
济宁 114
聊城 70
泰安 116
德州 71
菏泽 65
淄博 258
滨州 51
郑州 291
洛阳 129
许昌 69
南阳 152
信阳 66
濮阳 54
焦作 58
新乡 90
合肥 814
六安 114
蚌埠 82
淮北 63
宿州 104
阜阳 114
杭州 902
武汉 621
襄阳 138
荆门 18
荆州 81
十堰 168
宜昌 76
南昌 287
九江 69
赣州 111
上饶 64
长沙 617
岳阳 61
株洲 49
衡阳 102
湘潭 78
湖州 102
嘉兴 274
绍兴 98
宁波 415
金华 239
台州 177
温州 245
重庆 899
张家口 66
呼和浩特 116
太原 306
包头 68
大同 16
运城 102
西安 643
咸阳 50
渭南 70
宝鸡 90
乌鲁木齐 96
银川 141
西宁 44
成都 1810
资阳 71
眉山 61
宜宾 48
乐山 70
绵阳 123
南充 105
自贡 109
德阳 103
'''
city_info = {}
city_info = {}
for line in city_str.split('\n'):
tmp = line.split('\t')
if len(tmp) < 2:
print('异常数据:', line)
continue
# 加“市”字,注意,少数市不以市结尾
city_info[tmp[0]+'市'] = int(tmp[1])
city_info
全国地图——省份
from pyecharts import options as opts
from pyecharts.globals import ThemeType
from pyecharts.charts import Map#主题
# 省会及直辖市
data = [['江苏', 492], ['安徽', 830], ['湖南', 879], ['河南', 1073], ['浙江', 1092], ['广东', 1151], ['天津', 94], ['内蒙古', 58],
['北京', 337], ['陕西', 213], ['广西', 210], ['宁夏', 49], ['贵州', 109], ['上海', 295], ['江西', 771], ['福建', 261],
['新疆', 49], ['四川', 405], ['云南', 141], ['海南', 136], ['山东', 459], ['吉林', 80], ['黑龙江', 331], ['河北', 218],
['香港', 36], ['重庆', 468], ['山西', 119], ['甘肃', 83], ['湖北', 29631], ['辽宁', 107], ['台湾', 18], ['澳门', 10],
['青海', 18], ['西藏', 1]]
# 方法一 设置地图参数
map = (
Map(init_opts=opts.InitOpts(bg_color="#FFFAFA", theme=ThemeType.ESSOS,width=1000))
.add("确诊人数", data)
.set_global_opts(
title_opts=opts.TitleOpts(title="fungis-基于丁香园数据的疫情图"),
# visualmap_opts=opts.VisualMapOpts(max_=2000),#使用系统默认label,最大区间值,因图而异
visualmap_opts=opts.VisualMapOpts( # 定制label区间、名称
is_piecewise=True, # 设置是否为分段显示
# 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
pieces=[
{"min": 2000, "label": '>2000人', "color": "#eb2f06"},
{"min": 1000, "max": 2000, "label": '1001-2000人', "color": "#FF3030"}, # 不指定 max,表示 max 为无限大(Infinity)。
{"min": 500, "max": 1000, "label": '500-1000人', "color": "#FF4500"},
{"min": 100, "max": 499, "label": '100-499人', "color": "#FF7F50"},
{"min": 10, "max": 99, "label": '10-99人', "color": "#FFA500"},
{"min": 1, "max": 9, "label": '1-9人', "color": "#FFDEAD"},
],
# 两端的文本,如['High', 'Low']。
range_text=['高', '低'],
)
)
)
map.render(path="./html/中国疫情人数区间地图1.html")
城市区县地图
全国一共372个城市
from pyecharts.charts import Map
from pyecharts import options as opts
from pyecharts.globals import ThemeType # 主题
# 各个城市相关数据
data = [['信阳市', 220], ['南阳市', 134], ['郑州市', 130], ['驻马店市', 123], ['商丘市', 83], ['周口市', 65], ['平顶山市', 52], ['新乡市', 46],
['安阳市', 45], ['许昌市', 31], ['漯河市', 30], ['洛阳市', 27], ['焦作市', 25], ['开封市', 24], ['鹤壁市', 17], ['濮阳市', 10],
['三门峡市', 7], ['济源市', 4]]
cityName = ['信阳市', '南阳市', '郑州市', '驻马店市', '商丘市', '周口市', '平顶山市', '新乡市', '安阳市', '许昌市', '漯河市', '洛阳市', '焦作市', '开封市', '鹤壁市',
'濮阳市', '三门峡市', '济源市']
confirmedCount = [220, 134, 130, 123, 83, 65, 52, 46, 45, 31, 30, 27, 25, 24, 17, 10, 7, 4]
curedCount = [28, 28, 34, 14, 9, 11, 12, 6, 10, 2, 6, 2, 1, 1, 3, 0, 3, 0]
deadCount = [0, 2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
map = (
# 初始化配置项中可以设置画布宽高,背景色和主题
Map(init_opts=opts.InitOpts(bg_color="#FFFAFA", theme=ThemeType.ROMANTIC, width=1000))
.add("确诊人数", data, "河南", is_map_symbol_show=False,
# 【2021-9-1】地图上显示数值
label_opts=opts.LabelOpts(
is_show=True,
formatter=JsCode("function(data){return data.value;}"),
),
) # 设置是否显示地图上的小红点
.set_global_opts(
# 标题配置项,pos_left可取值center、left、right、5%等等
title_opts=opts.TitleOpts(title="河南疫情确诊人数分布图-fungis", pos_left="left"),
visualmap_opts=opts.VisualMapOpts(
is_piecewise=True, # 设置是否为分段显示
# 自定义的每一段的范围,以及每一段的文字,以及每一段的特别的样式。例如:
pieces=[
{"min": 201, "label": '>200人', "color": "#e55039"}, # 不指定 max,表示 max 为无限大(Infinity)。
{"min": 101, "max": 200, "label": '101-200人', "color": "#FF4500"},
{"min": 51, "max": 100, "label": '51-100人', "color": "#FF7F50"},
{"min": 10, "max": 50, "label": '10-50人', "color": "#FFA500"},
{"min": 1, "max": 9, "label": '1-9人', "color": "#FFDEAD"},
],
# 两端的文本,如['High', 'Low']。
range_text=['高', '低'],
),
)
)
map.render(path="./河南疫情确诊人数分布图1.html")
世界地图
世界地图
- 国家名用英文
from pyecharts import options as opts
from pyecharts.charts import Map
from pyecharts.faker import Faker
c = (
Map(init_opts=opts.InitOpts(width="1400px", height="1000px"))
.add("商家A", [list(z) for z in zip(Faker.country, Faker.values())], "world")
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="Map-世界地图"),
visualmap_opts=opts.VisualMapOpts(max_=200),
)
.render("map_world.html")
)
提供sql,csv,json格式的世界位置信息数据下载,包含洲,国家,省份(州),区(市),县,美国又分了几大区域,提供中文,英文,编码等相关信息,各级关系链式存储。
# 世界国家中英文对照表
country_map = {
"Afghanistan":"阿富汗",
"Aland Islands":"奥兰群岛",
"Albania":"阿尔巴尼亚",
"Algeria":"阿尔及利亚",
"American Samoa":"美属萨摩亚",
"Andorra":"安道尔",
"Angola":"安哥拉",
"Anguilla":"安圭拉",
"Antigua and Barbuda":"安提瓜和巴布达",
"Argentina":"阿根廷",
"Armenia":"亚美尼亚",
"Aruba":"阿鲁巴",
"Australia":"澳大利亚",
"Austria":"奥地利",
"Azerbaijan":"阿塞拜疆",
"Bangladesh":"孟加拉",
"Bahrain":"巴林",
"Bahamas":"巴哈马",
"Barbados":"巴巴多斯",
"Belarus":"白俄罗斯",
"Belgium":"比利时",
"Belize":"伯利兹",
"Benin":"贝宁",
"Bermuda":"百慕大",
"Bhutan":"不丹",
"Bolivia":"玻利维亚",
"Bosnia and Herzegovina":"波斯尼亚和黑塞哥维那",
"Botswana":"博茨瓦纳",
"Bouvet Island":"布维岛",
"Brazil":"巴西",
"Brunei":"文莱",
"Bulgaria":"保加利亚",
"Burkina Faso":"布基纳法索",
"Burundi":"布隆迪",
"Cambodia":"柬埔寨",
"Cameroon":"喀麦隆",
"Canada":"加拿大",
"Cape Verde":"佛得角",
"Central African Republic":"中非",
"Chad":"乍得",
"Chile":"智利",
"Christmas Islands":"圣诞岛",
"Cocos (keeling) Islands":"科科斯(基林)群岛",
"Colombia":"哥伦比亚",
"Comoros":"科摩罗",
"Congo (Congo-Kinshasa)":"刚果(金)",
"Congo":"刚果",
"Cook Islands":"库克群岛",
"Costa Rica":"哥斯达黎加",
"Cote D’Ivoire":"科特迪瓦",
"China":"中国",
"Croatia":"克罗地亚",
"Cuba":"古巴",
"Czech":"捷克",
"Cyprus":"塞浦路斯",
"Denmark":"丹麦",
"Djibouti":"吉布提",
"Dominica":"多米尼加",
"East Timor":"东帝汶",
"Ecuador":"厄瓜多尔",
"Egypt":"埃及",
"Equatorial Guinea":"赤道几内亚",
"Eritrea":"厄立特里亚",
"Estonia":"爱沙尼亚",
"Ethiopia":"埃塞俄比亚",
"Faroe Islands":"法罗群岛",
"Fiji":"斐济",
"Finland":"Finland",
"France":"法国",
"Franch Metropolitan":"法国大都会",
"Franch Guiana":"法属圭亚那",
"French Polynesia":"法属波利尼西亚",
"Gabon":"加蓬",
"Gambia":"冈比亚",
"Georgia":"格鲁吉亚",
"Germany":"德国",
"Ghana":"加纳",
"Gibraltar":"直布罗陀",
"Greece":"希腊",
"Grenada":"格林纳达",
"Guadeloupe":"瓜德罗普岛",
"Guam":"关岛",
"Guatemala":"危地马拉",
"Guernsey":"根西岛",
"Guinea-Bissau":"几内亚比绍",
"Guinea":"几内亚",
"Guyana":"圭亚那",
"Hong Kong":"香港 (中国)",
"Haiti":"海地",
"Honduras":"洪都拉斯",
"Hungary":"匈牙利",
"Iceland":"冰岛",
"India":"印度",
"Indonesia":"印度尼西亚",
"Iran":"伊朗",
"Iraq":"伊拉克",
"Ireland":"爱尔兰",
"Isle of Man":"马恩岛",
"Israel":"以色列",
"Italy":"意大利",
"Jamaica":"牙买加",
"Japan":"日本",
"Jersey":"泽西岛",
"Jordan":"约旦",
"Kazakhstan":"哈萨克斯坦",
"Kenya":"肯尼亚",
"Kiribati":"基里巴斯",
"Korea (South)":"韩国",
"Korea (North)":"朝鲜",
"Kuwait":"科威特",
"Kyrgyzstan":"吉尔吉斯斯坦",
"Laos":"老挝",
"Latvia":"拉脱维亚",
"Lebanon":"黎巴嫩",
"Lesotho":"莱索托",
"Liberia":"利比里亚",
"Libya":"利比亚",
"Liechtenstein":"列支敦士登",
"Lithuania":"立陶宛",
"Luxembourg":"卢森堡",
"Macau":"澳门(中国)",
"Macedonia":"马其顿",
"Malawi":"马拉维",
"Malaysia":"马来西亚",
"Madagascar":"马达加斯加",
"Maldives":"马尔代夫",
"Mali":"马里",
"Malta":"马耳他",
"Marshall Islands":"马绍尔群岛",
"Martinique":"马提尼克岛",
"Mauritania":"毛里塔尼亚",
"Mauritius":"毛里求斯",
"Mayotte":"马约特",
"Mexico":"墨西哥",
"Micronesia":"密克罗尼西亚",
"Moldova":"摩尔多瓦",
"Monaco":"摩纳哥",
"Mongolia":"蒙古",
"Montenegro":"黑山",
"Montserrat":"蒙特塞拉特",
"Morocco":"摩洛哥",
"Mozambique":"莫桑比克",
"Myanmar":"缅甸",
"Namibia":"纳米比亚",
"Nauru":"瑙鲁",
"Nepal":"尼泊尔",
"Netherlands":"荷兰",
"New Caledonia":"新喀里多尼亚",
"New Zealand":"新西兰",
"Nicaragua":"尼加拉瓜",
"Niger":"尼日尔",
"Nigeria":"尼日利亚",
"Niue":"纽埃",
"Norfolk Island":"诺福克岛",
"Norway":"挪威",
"Oman":"阿曼",
"Pakistan":"巴基斯坦",
"Palau":"帕劳",
"Palestine":"巴勒斯坦",
"Panama":"巴拿马",
"Papua New Guinea":"巴布亚新几内亚",
"Paraguay":"巴拉圭",
"Peru":"秘鲁",
"Philippines":"菲律宾",
"Pitcairn Islands":"皮特凯恩群岛",
"Poland":"波兰",
"Portugal":"葡萄牙",
"Puerto Rico":"波多黎各",
"Qatar":"卡塔尔",
"Reunion":"留尼汪岛",
"Romania":"罗马尼亚",
"Rwanda":"卢旺达",
"Russian Federation":"俄罗斯联邦",
"Saint Helena":"圣赫勒拿",
"Saint Kitts-Nevis":"圣基茨和尼维斯",
"Saint Lucia":"圣卢西亚",
"Saint Vincent and the Grenadines":"圣文森特和格林纳丁斯",
"El Salvador":"萨尔瓦多",
"Samoa":"萨摩亚",
"San Marino":"圣马力诺",
"Sao Tome and Principe":"圣多美和普林西比",
"Saudi Arabia":"沙特阿拉伯",
"Senegal":"塞内加尔",
"Seychelles":"塞舌尔",
"Sierra Leone":"塞拉利昂",
"Singapore":"新加坡",
"Serbia":"塞尔维亚",
"Slovakia":"斯洛伐克",
"Slovenia":"斯洛文尼亚",
"Solomon Islands":"所罗门群岛",
"Somalia":"索马里",
"South Africa":"南非",
"Spain":"西班牙",
"Sri Lanka":"斯里兰卡",
"Sudan":"苏丹",
"Suriname":"苏里南",
"Swaziland":"斯威士兰",
"Sweden":"瑞典",
"Switzerland":"瑞士",
"Syria":"叙利亚",
"Tajikistan":"塔吉克斯坦",
"Tanzania":"坦桑尼亚",
"Taiwan":"台湾 (中国)",
"Thailand":"泰国",
"Trinidad and Tobago":"特立尼达和多巴哥",
"Timor-Leste":"东帝汶",
"Togo":"多哥",
"Tokelau":"托克劳",
"Tonga":"汤加",
"Tunisia":"突尼斯",
"Turkey":"土耳其",
"Turkmenistan":"土库曼斯坦",
"Tuvalu":"图瓦卢",
"Uganda":"乌干达",
"Ukraine":"乌克兰",
"United Arab Emirates":"阿拉伯联合酋长国",
"United Kingdom":"英国",
"United States":"美国",
"Uruguay":"乌拉圭",
"Uzbekistan":"乌兹别克斯坦",
"Vanuatu":"瓦努阿图",
"Vatican City":"梵蒂冈",
"Venezuela":"委内瑞拉",
"Vietnam":"越南",
"Wallis and Futuna":"瓦利斯群岛和富图纳群岛",
"Western Sahara":"西撒哈拉",
"Yemen":"也门",
"Yugoslavia":"南斯拉夫",
"Zambia":"赞比亚",
"Zimbabwe":"津巴布韦"
}
country_map_ch2en = dict(zip(country_map.values(), country_map.keys()))
bot_pv_sample_str = """
牙买加 104 1 104
基里巴斯 23 1 23
利比亚 19 1 19
肯尼亚 15 1 15
印度 45 3 15
马来西亚 17,685 1,420 12.4500
美国 556 58 9.5900
摩洛哥 19 2 9.5000
菲律宾 60,353 6,708 9
厄瓜多尔 345 40 8.6300
沙特阿拉伯 1,526 183 8.3400
西班牙 8 1 8
日本 946 121 7.8200
危地马拉 23 3 7.6700
印度尼西亚 91,182 12,038 7.5700
孟加拉国 68 9 7.5600
巴西 4,441 589 7.5400
文莱 22 3 7.3300
伊拉克 7 1 7
NULL 1,437 222 6.4700
玻利维亚 211 33 6.3900
韩国 341 55 6.2000
墨西哥 14,912 2,434 6.1300
智利 1,805 297 6.08000
以色列 6 1 6
巴基斯坦 6 1 6
加纳 12 2 6
新加坡 523 88 5.9400
阿根廷 13,816 2,359 5.8600
洪都拉斯 11 2 5.5000
泰国 1,217 227 5.3600
秘鲁 18,537 3,541 5.2300
英国 3 2 1.5000
尼加拉瓜 1 1 1
阿尔及利亚 1 1 1
意大利 1 1 1
"""
# [国家, 会话轮数, 会话个数, 平均会话轮数]
bot_pv_sample = [ i.split('\t') for i in bot_pv_sample_str.replace(',', '').split('\n') if i!='']
bot_pv_sample
from pyecharts import options as opts
from pyecharts.charts import Map
#from pyecharts.faker import Faker
# 世界地图数据
country = [country_map_ch2en[i[0]] for i in bot_pv_sample if i[0] in country_map_ch2en]
value = [int(i[1]) for i in bot_pv_sample if i[0] in country_map_ch2en]
c = (
Map(init_opts=opts.InitOpts(width="1400px", height="1000px"))
#.add("会话轮数", [i[:2] for i in bot_pv_sample if i[0] in country_map_ch2en], "world")
.add("会话轮数", [list(z) for z in zip(country, value)], "world")
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="Map-世界地图"),
visualmap_opts=opts.VisualMapOpts(max_=max(value)),
)
.render("map_world.html")
)
三维显示
坐标点数据
from pyecharts import options as opts
from pyecharts.charts import Geo
from pyecharts.faker import Faker
c = (
Geo()
.add_schema(maptype="china")
.add("geo", [list(z) for z in zip(Faker.provinces, Faker.values())])
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(), title_opts=opts.TitleOpts(title="Geo-基本示例")
)
#.render("geo_base.html")
)
c.render_notebook()
3D全国地图
包含34个省市自治区数据
from pyecharts import options as opts
from pyecharts.charts import Map3D
from pyecharts.globals import ChartType
from pyecharts.commons.utils import JsCode
example_data = [
("北京", [116.4036, 39.9494, 100]),
("黑龙江", [127.9688, 45.368, 100]),
("内蒙古", [110.3467, 41.4899, 300]),
("吉林", [125.8154, 44.2584, 300]),
("辽宁", [123.1238, 42.1216, 300]),
("河北", [114.4995, 38.1006, 300]),
("天津", [117.4219, 39.4189, 300]),
("山西", [112.3352, 37.9413, 300]),
("陕西", [109.1162, 34.2004, 300]),
("甘肃", [103.5901, 36.3043, 300]),
("宁夏", [106.3586, 38.1775, 300]),
("青海", [101.4038, 36.8207, 300]),
("新疆", [87.9236, 43.5883, 300]),
("西藏", [91.11, 29.97, 300]),
("四川", [103.9526, 30.7617, 300]),
("重庆", [108.384366, 30.439702, 300]),
("山东", [117.1582, 36.8701, 300]),
("河南", [113.4668, 34.6234, 300]),
("江苏", [118.8062, 31.9208, 300]),
("安徽", [117.29, 32.0581, 300]),
("湖北", [114.3896, 30.6628, 300]),
("浙江", [119.5313, 29.8773, 300]),
("福建", [119.4543, 25.9222, 300]),
("江西", [116.0046, 28.6633, 300]),
("湖南", [113.0823, 28.2568, 300]),
("贵州", [106.6992, 26.7682, 300]),
("广西", [108.479, 23.1152, 300]),
("海南", [110.3893, 19.8516, 300]),
("上海", [121.4648, 31.2891, 300]),
("云南", [102.8816, 24.8668, 100]), # 昆明
("广东", [121.4648, 31.2891, 100]), # 广州
("香港", [114.2420, 22.2724, 100]),
("澳门", [113.5797, 22.1696, 100]),
("台湾", [121.5917, 25.0346, 100]), # 台北
]
c = (
Map3D(init_opts=opts.InitOpts(width="1400px", height="700px"))
.add_schema(
itemstyle_opts=opts.ItemStyleOpts(
color="rgb(5,101,123)",
opacity=1,
border_width=0.8,
border_color="rgb(62,215,213)",
),
map3d_label=opts.Map3DLabelOpts(
is_show=False,
formatter=JsCode("function(data){return data.name + " " + data.value[2];}"),
),
emphasis_label_opts=opts.LabelOpts(
is_show=False,
color="#fff",
font_size=10,
background_color="rgba(0,23,11,0)",
),
light_opts=opts.Map3DLightOpts(
main_color="#fff",
main_intensity=1.2,
main_shadow_quality="high",
is_main_shadow=False,
main_beta=10,
ambient_intensity=0.3,
),
)
.add(
series_name="柱形图数据",
data_pair=example_data,
type_=ChartType.BAR3D, # 柱形图显示
# type_=ChartType.SCATTER3D, # 散点图显示
bar_size=1,
shading="lambert",
label_opts=opts.LabelOpts(
is_show=False,
formatter=JsCode("function(data){return data.name + ' ' + data.value[2];}"),
),
)
.set_global_opts(title_opts=opts.TitleOpts(title="城市数据"))
)
c.render("带有数据展示地图.html")
c.render_notebook()
世界地图-3D
import pyecharts.options as opts
from pyecharts.charts import MapGlobe
from pyecharts.faker import POPULATION
data = [x for _, x in POPULATION[1:]]
low, high = min(data), max(data)
c = (
MapGlobe(init_opts=opts.InitOpts(width="1400px", height="700px"))
.add_schema()
.add(
maptype="world",
series_name="World Population",
data_pair=POPULATION[1:],
is_map_symbol_show=False,
label_opts=opts.LabelOpts(is_show=False),
)
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(
min_=low,
max_=high,
range_text=["max", "min"],
is_calculable=True,
range_color=["lightskyblue", "yellow", "orangered"],
)
)
)
c.render("地球.html")
#c.render_notebook()
三维数据函数可视化
示例:
import math
from typing import Union
import pyecharts.options as opts
from pyecharts.charts import Surface3D
"""
Gallery 使用 pyecharts 1.1.0
参考地址: https://echarts.apache.org/examples/editor.html?c=surface-wave&gl=1
目前无法实现的功能:
1、暂时无法设置光滑表面 wireframe
2、暂时无法把 visualmap 进行隐藏
"""
def float_range(start: int, end: int, step: Union[int, float], round_number: int = 2):
"""
浮点数 range
:param start: 起始值
:param end: 结束值
:param step: 步长
:param round_number: 精度
:return: 返回一个 list
"""
temp = []
while True:
if start < end:
temp.append(round(start, round_number))
start += step
else:
break
return temp
def surface3d_data():
for t0 in float_range(-3, 3, 0.05):
y = t0
for t1 in float_range(-3, 3, 0.05):
x = t1
z = math.sin(x ** 2 + y ** 2) * x / 3.14
yield [x, y, z]
(
Surface3D(init_opts=opts.InitOpts(width="1600px", height="800px"))
.add(
series_name="",
shading="color",
data=list(surface3d_data()),
xaxis3d_opts=opts.Axis3DOpts(type_="value"),
yaxis3d_opts=opts.Axis3DOpts(type_="value"),
grid3d_opts=opts.Grid3DOpts(width=100, height=40, depth=100),
)
.set_global_opts(
visualmap_opts=opts.VisualMapOpts(
dimension=2,
max_=1,
min_=-1,
range_color=[
"#313695",
"#4575b4",
"#74add1",
"#abd9e9",
"#e0f3f8",
"#ffffbf",
"#fee090",
"#fdae61",
"#f46d43",
"#d73027",
"#a50026",
],
)
)
.render("surface_wave.html")
)
词云
【2022-1-21】词云可视化效果展示,包含静态、动态三维词云
WordCloud.add() 方法简介
add(name,attr,value,
shape="circle",
word_gap=20,
word_size_range=None,
rotate_step=45)
# -----------
name str # 图例名称
attr list # 属性名称
value list # 属性所对应的值
shape # 词云图轮廓 对应属性可选'circle', 'rect', 'roundRect', 'triangle', 'diamond', 'pin', 'arrow'
word_gap int # 单词间隔, 字符间隔默认为20
word_size_range # 单词字体大小范围, 字符范围默认为[12,60]
rotate_step int # 旋转角度默认为45
关键词可视化
直接根据关键词信息绘制词云
# import pyecharts as pe
from pyecharts.charts import Tab
from pyecharts.charts import WordCloud
all_info = {'tag':{'美国生活': 2, '移民': 2}, 'to':{'三源英华郡': 2, '十堰广润锦绣华府': 1}}
tab = Tab()
w1 = WordCloud()
test_data = list(all_info['tag'].items())
#test_data = [['a',3],['b',10]]
w1.add(series_name="房源测评-话题分布", data_pair=test_data)
# 【2023-5-11】注意:上界不能只是+1,需要留一定空间
tab.add(w1, "话题分布")
w2 = WordCloud()
test_data = list(all_info['tag'].items())
#test_data = [['a',3],['b',10]]
w2.add(series_name="房源测评-提醒人分布", data_pair=test_data)
tab.add(w2, "提醒人分布")
tab.render('词云.html')
tab.render_notebook()
文本关键词可视化
# -------- 词云可视化 ----------
import jieba
from collections import Counter
from pyecharts.charts import WordCloud
for line in file_object:
item = json.loads(line)
if item == None:
continue
text = item['text']
seg_list = jieba.cut(text, cut_all=False)
text_list.extend(seg_list)
# 词频统计,使用Count计数方法
words_counter = Counter(text_list)
# 将Counter类型转换为列表
words_list = words_counter.most_common(500)
(
WordCloud()
.add(series_name="", data_pair=words, word_size_range=[20, 66])
.render("词云.html")
)
分页混合
overlap 重叠
- 方法:
- 旧版的import overlap
- 新版直接调用overlap方法即可
- 代码: overlap_bar_line.py
- 示例:折线图于散点图重叠
from pyecharts import options as opts
from pyecharts.charts import Bar, Line
from pyecharts.faker import Faker
v1 = [2.0, 4.9, 7.0, 23.2, 25.6, 76.7, 135.6, 162.2, 32.6, 20.0, 6.4, 3.3]
v2 = [2.6, 5.9, 9.0, 26.4, 28.7, 70.7, 175.6, 182.2, 48.7, 18.8, 6.0, 2.3]
v3 = [2.0, 2.2, 3.3, 4.5, 6.3, 10.2, 20.3, 23.4, 23.0, 16.5, 12.0, 6.2]
bar = (
Bar()
.add_xaxis(Faker.months)
.add_yaxis("蒸发量", v1)
.add_yaxis("降水量", v2)
.extend_axis(
yaxis=opts.AxisOpts(
axislabel_opts=opts.LabelOpts(formatter="{value} °C"), interval=5
)
)
.set_series_opts(label_opts=opts.LabelOpts(is_show=False))
.set_global_opts(
title_opts=opts.TitleOpts(title="Overlap-bar+line"),
yaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter="{value} ml")),
)
)
line = Line().add_xaxis(Faker.months).add_yaxis("平均温度", v3, yaxis_index=1)
bar.overlap(line) # 表格重叠
#bar.render("overlap_bar_line.html")
bar.render_notebook()
折线图于散点图重叠
from pyecharts import options as opts
from pyecharts.charts import Line, Scatter
from pyecharts.faker import Faker
x = Faker.choose()
line = (
Line()
.add_xaxis(x)
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="Overlap-line+scatter"))
)
scatter = (
Scatter()
.add_xaxis(x)
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
)
line.overlap(scatter)
line.render("overlap_line_scatter.html")
Grid 网格组装
定义一个Grid示例,依次加入子图,设置位置(opts.GridOpts)
水平/垂直组装
from pyecharts import options as opts
from pyecharts.charts import Bar, Grid, Line
from pyecharts.faker import Faker
bar = (
Bar()
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(title_opts=opts.TitleOpts(title="Grid-Bar"))
)
line = (
Line()
.add_xaxis(Faker.choose())
.add_yaxis("商家A", Faker.values())
.add_yaxis("商家B", Faker.values())
.set_global_opts(
title_opts=opts.TitleOpts(title="Grid-Line", pos_top="48%"),
legend_opts=opts.LegendOpts(pos_top="48%"),
)
)
grid = (
Grid()
# ----- 垂直组装 ------
.add(bar, grid_opts=opts.GridOpts(pos_bottom="60%"))
.add(line, grid_opts=opts.GridOpts(pos_top="60%"))
# ----- 水平组装 -------
#.add(scatter, grid_opts=opts.GridOpts(pos_left="55%"))
#.add(line, grid_opts=opts.GridOpts(pos_right="55%"))
.render("grid_vertical.html")
)
多Y轴
Tab页
- 【2021-8-21】多种图类型分布在一个页面的多个tab页
import pyecharts.options as opts
from pyecharts.charts import Bar, Pie, Page, Tab
from pyecharts.components import Table
# 示例数据
train_list = [['NLU00000',
'还有双鸭山到淮阴的汽车票吗13号的',
'Travel-Query',
'destination:淮阴+departure:双鸭山+datetime_date:13号+query_type:汽车票'],
['NLU00001', '从这里怎么回家', 'Travel-Query', 'destination:家+query_type:导航'],
['NLU00002', '随便播放一首专辑阁楼里的佛里的歌', 'Music-Play', 'album:阁楼+play_mode:随机播放'],
['NLU00003', '给看一下墓王之王嘛', 'FilmTele-Play', 'name:墓王之王'],
['NLU00004',
'我想看挑战两把s686打突变团竞的游戏视频',
'Video-Play',
'name:挑战两把s686打突变团竞的游戏视频'],
['NLU00005', '我想看和平精英上战神必备技巧的游戏视频', 'Video-Play', 'name:和平精英上战神必备技巧的游戏视频'],
['NLU00006',
'2019年古装爱情电视剧小女花不弃的花絮播放一下',
'Video-Play',
'name:小女花不弃的花絮+datetime_date:2019年'],
['NLU00007', '找一个2004年的推理剧给我看一会呢', 'FilmTele-Play', 'tag:推理+age:2004年'],
['NLU00008',
'自驾游去深圳都经过那些地方啊',
'Travel-Query',
'destination:深圳+query_type:导航'],
['NLU00009',
'给我转播今天的女子双打乒乓球比赛现场',
'Video-Play',
'datetime_date:今天+name:女子双打乒乓球比赛现场']]
stat_info = {'intent': {'Travel-Query': 1000,
'Music-Play': 1000,
'FilmTele-Play': 1000,
'Video-Play': 1000,
'Radio-Listen': 1000,
'HomeAppliance-Control': 1000,
'Weather-Query': 1000,
'Alarm-Update': 1000,
'Calendar-Query': 1000,
'TVProgram-Play': 50,
'Audio-Play': 50},
'slot': {'destination': 917,
'departure': 384,
'datetime_date': 3244,
'query_type': 945,
'album': 158,
'play_mode': 396,
'name': 2236,
'tag': 384,
'age': 367,
'artist': 1150,
'channel': 622,
'song': 424,
'instrument': 109,
'appliance': 963,
'command': 994,
'details': 652,
'index': 503,
'city': 840,
'datetime_time': 1143,
'notes': 696,
'play_setting': 233,
'language': 152,
'type': 419,
'region': 458,
'frequency': 331}}
all_num = {}
table_data = {}
for name in ('intent', 'slot'):
all_num[name] = sum(stat_info[name].values())
table_data[name] = [[k,v,'{:.2f}'.format(v*100/all_num[name])] for k,v in stat_info[name].items()]
# ============== 表格 =============
table_sample = Table()
headers = ['id', 'text', 'intent', 'slot_info']
rows = train_list
table_sample.add(headers, rows).set_global_opts(
title_opts=opts.ComponentTitleOpts(title="训练集数据示例")
)
table_intent = Table()
headers = ["意图名", "频次", "占比(%)"]
rows = table_data['intent']
table_intent.add(headers, rows).set_global_opts(
title_opts=opts.ComponentTitleOpts(title="意图分布")
)
table_slot = Table()
headers = ["槽位名", "频次", "占比(%)"]
rows = table_data['slot']
table_slot.add(headers, rows).set_global_opts(
title_opts=opts.ComponentTitleOpts(title="槽位分布")
)
# ============== 柱形图 =============
bar_intent = (Bar()
.add_xaxis(list(stat_info['intent'].keys()))
.add_yaxis("意图", list(stat_info['intent'].values()))
.set_global_opts(
title_opts=opts.TitleOpts(title="意图频次"),
#datazoom_opts=[opts.DataZoomOpts()], # 拖拽功能
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
)
)
bar_slot = (Bar()
.add_xaxis(list(stat_info['slot'].keys()))
.add_yaxis("槽位", list(stat_info['slot'].values()))
.set_global_opts(
title_opts=opts.TitleOpts(title="槽位频次"),
#datazoom_opts=[opts.DataZoomOpts()],
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
)
)
# ============== 饼图 =============
pie_intent = (Pie()
.add("意图分布", list(stat_info['intent'].items()),
radius=["30%", "75%"], # radius=[40,75],radiius:半径
center=["25%", "50%"],
rosetype="radius",
label_opts=opts.LabelOpts(is_show=True))
.set_global_opts(
title_opts=opts.TitleOpts(title="意图占比分布"), # TitleOpts:标题设置项
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
legend_opts=opts.LegendOpts(pos_top="5%",pos_right="15%", orient='vertical')) #LegendOpts:图例配置项
)
pie_slot = (Pie()
.add("槽位分布", list(stat_info['slot'].items()),
radius=["30%", "75%"], # radius=[40,75],radiius:半径
center=["25%", "50%"],
rosetype="radius",
label_opts=opts.LabelOpts(is_show=True))
.set_global_opts(
title_opts=opts.TitleOpts(title="槽位占比分布"), # TitleOpts:标题设置项
toolbox_opts=opts.ToolboxOpts(is_show=True), # 工具箱
legend_opts=opts.LegendOpts(pos_top="5%",pos_right="15%", orient='vertical')) #LegendOpts:图例配置项
)
#pie.render("环形图.html")
#pie.render_notebook()
# ============== 汇总 =============
# 绘制在一张图里
# page = Page(layout=Page.SimplePageLayout)
# page.add(table_sample, table_intent, table_slot, bar_intent, bar_slot, pie_intent, pie_slot)
# page.render("ccf.html")
# page.render_notebook()
tab = Tab()
tab.add(table_sample, "训练数据样例")
tab.add(table_intent, "意图分布-表")
tab.add(table_slot, "槽位分布-表")
tab.add(bar_intent, "意图分布-柱形图")
tab.add(bar_slot, "槽位分布-柱形图")
tab.add(pie_intent, "意图分布-饼图")
tab.add(pie_slot, "槽位分布-饼图")
tab.render("ccf.html")
tab.render_notebook()
smartchart
- 【2021-1-2】smartchart
- 安装
#安装SmartChart
pip3 install smartchart
pip3 install smartchart -U #(升级)
# 如果安装过程慢,建意使用
pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple smartchart
#如果你是第一次安装SmartChart(注意,非第一次不要执行,会覆盖原有DB)
pip3 install smartdb # (初始化DB)
PyGraphviz
Graphviz 是一个开源的图可视化工具,非常适合绘制结构化的图标和网络。Graphviz 使用一种叫 DOT 的语言来表示图形。
介绍
- 【2020-8-4】PyGraphviz (几何图形可视化工具) 简单入门
- Graphviz 是一个几何图形可视化软件,能够将数据的结构信息表示为抽象图形和网络图的方式。
- PyGraphviz 主要对数据量大、可任意定制的图形上具有强大优势。
- 建议:由于 PyGraphviz 暂时无法对同源节点合并线段。在流程图、小型结构图方面,Visio 可以作为 Graphviz 的直接替代软件。
工具
【2024-7-5】dot文件在线可视化
- GraphvizOnline, 左侧输入dot文本,右侧实时展示图
DOT 语言
DOT语言是一种图形描述语言。能够以简单的方式描述图形,并且为人和计算机所理解。
digraph graphname{
a -> {b c};
c -> e;
b -> d; // 有向图
subgraph cluster_bc {
bgcolor=red;
b;
c;
}
subgraph cluster_de {
label="Block"
d;
e;
}
dot 文件解析
【2024-7-6】使用正则表达式抽取 dot 文件中的节点边信息,转化成 pandas 表格
dot 文件示例
digraph g {
"000" -> "000" [ label="0", color="Red" ];
"000" -> "001" [ label="1", color="Blue" ];
"000" -> "002" [ label="2", color="Green" ];
"000" -> "003" [ label="3", color="Yellow" ];
}
解析代码
import pandas as pd
import re
# "223" -> "231" [ label="1", color="Blue" ];
pattern = re.compile(r'.*\"(.*?)\".*\"(.*?)\".*\[\s+label=\"(.*?)\".*color=\"(.*?)\".*\]')
data_file = 'test.dot'
data_list = []
with open(data_file, 'r') as f:
for line in f.readlines():
res = pattern.findall(line)
if not res:
continue
# [('000', '000', '0', 'Red')]
data_list.append(res[0])
#print(res)
print(data_list)
#!cat test.dot
df = pd.DataFrame(data_list, columns=['source', 'target', 'edge_name', 'edge_color'])
df
安装
- 各操作系统下的安装
brew install graphviz # mac
pip install graphviz # linux
conda install graphviz # conda
使用
import pygraphviz as pgv
# 创建图形
G = pgv.AGraph(directed=True, strict=False, nodesep=0, ranksep=1.2, rankdir="TB",
splines="none", concentrate=True, bgcolor="write",
compound=True, normalize=False, encoding='UTF-8')
# 添加节点
G.add_node(name, label=None, fontname="Times-Roman", fontsize=14,
shape="ellipse", style="rounded", color="black", fontcolor="black",
pos="x,y(!)", fixedsize=False, width=1, height=1)
G.add_nodes_from(names, **attr) # 批量添加点,参数同上
# 添加边
G.add_edge(origin, target, color="black", style="solid", penwidth=1,
label="", fontname="Times-Roman", fontsize=14, fontcolor="black",
arrowsize=1, arrowhead="normal", arrowtail="normal", dir="forward")
# label -> str:边标签,未指定时不显示
# penwidth:线条粗细
# arrowsize:箭头大小
# arrowhead:箭头类型,可选 normal, vee
# dir:箭头方向,可选 both, forward, back, none。只有在无向图中才起作用!
G.add_nodes_from([[origin_1, target_1],
[origin_2, target_2],...], **attr) # 批量添加线,参数同上
# 导出图形
G.layout()
G.draw(file_name, prog="neato")
# prog:布局算法,可选 neato, dot (推荐), twopi, circo, fdp
- 创建图:
- directed -> False | True:有向图
- strict -> True | False:简单图
- nodesep:同级节点最小间距
- ranksep:不同级节点最小间距
- rankdir:绘图方向,可选 TB (从上到下), LR (从左到右), BT (从下到上), RL (从右到左)
- splines:线条类型,可选 ortho (直角), polyline (折线), spline (曲线), line (线条), none (无)
- concentrate -> True | False:合并线条 (双向箭头)
- bgcolor:背景颜色
- compound -> True | False:多子图时,不允许子图相互覆盖
- normalize -> False | True:以第一个节点作为顶节点
- 添加节点
- name -> str:节点名。label 为节点标签,未指定时显示 name
- fontname:字体名称,常用:Microsoft YaHei, SimHei, KaiTi, SimSun, FangSong, Times-Roman, Helvetica, Courier。可以使用 “times bold italic” 表示字体类型、粗细、倾斜
- fixedsize -> Flase | True | “shape”`:固定大小,默认随文本长度变化。设置为 True 时,width 和 height 参数共同控制点大小。设置为 “shape” 时,将取标签文本和设置值的较大者
- pos -> str:点的初始位置。使用 “x,y!” 时,可以强制固定点的位置。
- style:节点线样式,使用
color
设置线条颜色 (style=”filled” 时,设置填充颜色) - shape: 节点形状
案例
networkx 绘制社交网络图
networkx模块以及pyvis模块
import networkx as nx
g = nx.Graph()
# 点
g.add_node(0, label = "root") # intialize yourself as central node
g.add_node(1, label = "Company 1", size=10, title="info1")
g.add_node(2, label = "Company 2", size=40, title="info2")
g.add_node(3, label = "Company 3", size=60, title="info3")
# 边
g.add_edge(0, 1)
g.add_edge(0, 2)
g.add_edge(0, 3)
# -----------
g = nx.Graph()
g.add_node('myself') # 将自己放置在网络的中心
for _, row in df_position_reduced.iterrows():
g.add_node(position, size=count*2, title=hover_info, color='#3449eb')
g.add_edge('root', position, color='grey')
# 生成网络图表
nt = net.Network(height='700px', width='700px', bgcolor="black", font_color='white')
nt.from_nx(g)
nt.hrepulsion()
nt.show('company_graph.html')
因果关系图
- 效果:
- 代码:
import pygraphviz as pgv
G = pgv.AGraph(directed=True, strict=False, ranksep=0.2, splines="spline", concentrate=True)
# 设置节点标签
nodeA = "Police\nIntelligence"
nodeB = "Police Station"
nodeC = "Criminal Action"
nodeD = "Incidents"
nodeE = "Police Dockets"
nodeF = "Control Room\nAwareness"
nodeG = "Patroller Information"
nodeH = "Patroller Awareness"
# 添加节点
G.add_nodes_from([nodeA, nodeB, nodeC, nodeD, nodeE, nodeF, nodeG, nodeH],
color="#ffffff", fontname="times bold italic")
# 添加边
G.add_edges_from([[nodeA, nodeB], [nodeA, nodeF], [nodeB, nodeC], [nodeC, nodeD],
[nodeC, nodeG], [nodeD, nodeE], [nodeD, nodeG], [nodeE, nodeA],
[nodeF, nodeA], [nodeF, nodeG], [nodeF, nodeH], [nodeG, nodeF],
[nodeH, nodeG]], color="#7F01FF", arrowsize=0.8)
# 导出图形
G.layout()
G.draw("因果关系图.png", prog="dot")
因子相关性图
- 效果:
- 代码:
import pygraphviz as pgv
G = pgv.AGraph(directed=True, rankdir="TB")
# 设置节点标签
Root = "道路交通流畅"
negative_1 = "平均延误时间"
negative_2 = "负荷度"
negative_3 = "小区位置"
negative_4 = "相对延误率"
negative_5 = "房屋密度"
negative_6 = "人口密度"
negative_7 = "总延误率"
negative_8 = "排队率"
negative_9 = "行驶时间"
positive_1 = "通行能力"
positive_2 = "公路层级"
positive_3 = "路网结构"
positive_4 = "行驶速度"
positive_5 = "路网长度"
positive_6 = "小区面积"
positive_7 = "内部道路密度"
positive_8 = "路网密度"
# 添加节点
G.add_node(Root, style="filled", shape="box3d", color="#feb64d")
for negative in [eval(_) for _ in dir() if _.startswith("negative")]:
G.add_node(negative, style="filled", shape="ellipse", color="#CFDBF6")
for positive in [eval(_) for _ in dir() if _.startswith("positive")]:
G.add_node(positive, style="filled", shape="ellipse", color="#B4E7B7")
# 添加边
G.add_edges_from([[Root, negative_1], [Root, negative_6], [Root, negative_8], [Root, negative_9],
[negative_1, negative_2], [negative_1, negative_7], [negative_2, negative_3],
[negative_2, negative_7], [negative_3, negative_4], [negative_8, negative_9],
[positive_2, negative_5], [positive_3, negative_4], [positive_4, negative_5]],
color="#B4DBFF", style="dashed", penwidth=1.5)
G.add_edges_from([[Root, positive_1], [Root, positive_8], [negative_5, negative_4],
[negative_6, positive_4], [negative_5, positive_4], [negative_9, positive_5],
[positive_1, positive_2], [positive_2, positive_3], [positive_6, positive_5],
[positive_7, positive_6], [positive_8, positive_7]],
color="#B4E7B7", style="dashed", penwidth=1.5)
# 导出图形
G.layout()
G.draw("因子相关性图.png", prog="dot")
神经网络图
- 效果图:
- 代码:
import pygraphviz as pgv
G = pgv.AGraph(directed=True, rankdir="LR")
# 设置层数、每层节点数
network_structure = input("输入神经网络每层节点数,如:[10, 7, 5, 4, 2, 1]\n")
all_nodes = [[f"layer{layer_index}node{node_index}" for node_index in range(layer_nodes_num)] for
layer_index, layer_nodes_num in enumerate(eval(network_structure))]
# 添加输入层节点
for node_index, node in enumerate(all_nodes[0]):
G.add_node(node, label="", shape="circle", style="bold", color="#60acfc", pos=f"0,{0.6 * node_index}!")
# 添加输入层文本
G.add_node(f"Input_Layer", shape="none", label=f"Input_Layer({len(all_nodes[0])})",
pos=f"{0},{(node_index + 1) * 0.6}!")
# 添加中间层、输出层节点
for layer_index, layer in enumerate(all_nodes[1:]):
color = "#5bc49f" if layer_index == len(all_nodes[1:]) - 1 else "#ff7c7c"
for node_index, node in enumerate(layer):
x = 1.5 * (layer_index + 1)
y = - 0.3 * (len(all_nodes[layer_index + 1]) - len(all_nodes[0])) + 0.6 * node_index
G.add_node(node, label="", shape="circle", style="bold", color=color, pos=f"{x},{y}!")
# 添加中间层、输出层文本
text = f"Output_Layer({len(all_nodes[-1])})" if layer_index == len(all_nodes[1:]) - 1 else f"Layer_{layer_index + 1}({len(layer)})"
G.add_node(f"Layer_{layer_index + 1})", shape="none", label=text,
pos=f"{x},{y + 0.4}!")
# 添加线
for layer_index in range(all_nodes.__len__() - 1):
for start in all_nodes[layer_index]:
for end in all_nodes[layer_index + 1]:
G.add_edge(start, end)
# 导出图形
G.layout()
G.draw("神经网络.png")
# 运行代码,输入 [5, 10, 15, 15, 15, 10, 5, 1]
有限状态机FSM的可视化
- 有限状态机(Finite-state machine, FSM),又称有限状态自动机,简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。FSM是一种算法思想,简单而言,有限状态机由一组状态、一个初始状态、输入和根据输入及现有状态转换为下一个状态的转换函数组成。
- Transitions
- Python的Transitions库实现有限状态机(FSM)
from transitions.extensions import GraphMachine
states = ['first', 'second']
transitions = [
['any_trigger', 'first', 'first'],
['anything', '*', 'second'],
]
machine = GraphMachine(states=states, transitions=transitions, initial='first', auto_transitions=False, show_conditions=True)
machine.get_graph().draw('fsm.png', prog='dot')
from IPython.display import Image
Image('fsm.png')
- 结果,图
决策树可视化
【2023-1-31】决策树可视化,dtreeviz工具, XGBoost Examples
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import dtreeviz
iris = load_iris()
X = iris.data
y = iris.target
clf = DecisionTreeClassifier(max_depth=4)
clf.fit(X, y)
viz_model = dtreeviz.model(clf,
X_train=X, y_train=y,
feature_names=iris.feature_names,
target_name='iris',
class_names=iris.target_names)
v = viz_model.view() # render as SVG into internal object
v.show() # pop up window
v.save("/tmp/iris.svg") # optionally save as svg
turtle工具
turtle库的基础命令介绍
画布
画布cancas是绘图区域,可以设置它的大小和初始位置
turtle.screensize(1000,600,'red') # 大小的设置
turtle.setup(width=0.5,height=0.75) # 初始位置
画笔
(1)画笔运动的命令
turtle.forward(a) # 向当前画笔方向移动a像素长度
turtle.backward(a) # 向当前画笔相反方向移动a像素长度
turtle.right(a) # 顺时针移动
aturtle.left(a) # 逆时针移动
aturtle.pendown() # 移动时绘制图形
turtle.goto(x,y) # 将画笔移动到坐标为x,y的位置
turtle.penup() # 移动时不绘制图形,提起笔
turtle.speed(a) # 画笔绘制的速度范围
turtle.circle() # 画图,半径为正,表示圆心在画笔的左边画圈
(2)画笔控制命令
turtle.pensize(width) # 绘制图形的宽度
turtle.pencolor() # 画笔的颜色
turtle.fillcolor(a) # 绘制图形的填充颜色
turtle.color(a1,a2) # 同时设置pencolor=a1,fillcolor=a2
turtle.filling() # 返回当前是否在填充状态
turtle.begin_fill() # 准备开始填充图形
turtle.end_fill() # 填充完成
turtle.hideturtle() # 隐藏箭头显示
turtle.showturtle() # 显示箭头
(3)全局控制命令
turtle.clear() # 清空turtle窗口,但是turtle的位置和状态不会改变
turtle.reset() # 清空窗口,重置turtle状态为起始位置
turtle.undo() # 撤销上一个turtle动作
实战
原文涉及案例:樱花、玫瑰花、皮卡丘、星空、小黄人、单身狗等
爱心
from turtle import *
color('red', 'pink') # 画笔色red,背景色pink
begin_fill()
left(135) # 左转135°
fd(100) # 前进100像素
right(180) # 画笔掉头
circle(30, -180)
backward(35) # 由于此时画笔方向约为绝对方向的135°,需倒退画线
right(90)
forward(35)
circle(-30, 180)
fd(100)
end_fill()
hideturtle()
done()
动画
manim
【2023-6-14】manim中文教程
manim 简介
manim 是视频博主 3Blue1Brown 开发的动画引擎,他使用 manim 创作出了许多直观、美丽的数学科普内容。
manim 安装
安装方法
# mac 终端里分别输入
brew install py3cairo ffmpeg
brew install cmake pango scipy
pip3 install manim
#pip install manimgl
manimgl # 进入交互模式
hello world
manim 是运行在 python 下的,首先创建一个 python 文件 test.py
from manim import * # 导入 manim
class Test(Scene): # 定义一个场景
def construct(self):
#code here
circle = Circle() # 画圆
self.play(Write(circle)) # 动画
# 图片变化特效
cardi = SVGMobject("./images/cardiB.svg").shift(LEFT*3).scale(3)
iggy = SVGMobject("./images/iggy.svg").shift(RIGHT*3).scale(3)
self.play(Write(cardi), rate_func = smooth, run_time = 3) # 播放特效
self.wait(0.5) # 停顿 0.5 秒
self.play(ReplacementTransform(cardi, iggy),
rate_func = smooth, # 动画插值方式为贝塞尔曲线
run_time = 3 # 动画持续实践为 3 秒
)
self.wait(0.5)
# manim test.py Test
运行
manimgl test.py Test
屏幕上会弹出一个窗口,这时可以:
- 滚动鼠标中键来上下移动画面
- 按住键盘上 z 键的同时滚动鼠标中键来缩放画面
- 按住键盘上 f 键的同时移动鼠标来平移画面
- 按住键盘上 d 键的同时移动鼠标来改变三维视角
- 按下键盘上 r 键恢复到最初的视角
- 最后,按 q 来关闭窗口并退出程序.
manim 运行过程
manim 类继承的 pdf
运行过程
应用
transformer 结构动画
xinyu提供的脚本:flash-attn
- 【2023-6-16】调用 latex 报错: issue
No such file or directory … Tex/42c962cc458aefe6.svg’