python用plotly实现绘制局部放大图
作者:Eloik 发布时间:2021-06-13 06:30:44
标签:Python,Plotly
最终效果展示
实现思路
在绘图区域插入一个嵌入图,嵌入图与原图的绘画保持一致,通过限制嵌入图的x轴和y轴的显示范围,达到缩放的效果,并在原图上绘画一个矩形框,以凸显缩放的区域,最后通过两条直线凸显缩放关系。
导入库
import plotly.io as pio
import plotly.graph_objects as go
import pandas as pd
import numpy as np
# 设置plotly默认主题,白色主题
pio.templates.default = 'plotly_white'
随机生成一些数据
# x坐标
x = np.arange(1, 1001)
# 生成y轴数据,并添加随机波动
y1 = np.log(x)
indexs = np.random.randint(0, 1000, 800)
for index in indexs:
y1[index] += np.random.rand() - 0.5
y1 = y1 + 0.2
y2 = np.log(x)
indexs = np.random.randint(0, 1000, 800)
for index in indexs:
y2[index] += np.random.rand() - 0.5
y3 = np.log(x)
indexs = np.random.randint(0, 1000, 800)
for index in indexs:
y3[index] += np.random.rand() - 0.5
y3 = y3 - 0.2
封装绘图代码
class LocalZoomPlot:
def __init__(self, x, y, colors, x_range, scale=0.):
"""
:param x: x轴坐标,列表类型
:param y: y轴坐标,二维列表类型,例如 [y1, y2, y3]
:param colors: 每个曲线的颜色,必须与 len(y) 相等
:param x_range: 需要缩放区域的x轴范围
:param scale: 详见 getRangeMinMaxValue 函数
"""
self.x = x
self.y = y
self.colors = colors
self.x_range = x_range
self.y_range = self.getRangeMinMaxValue(x_range, scale)
def getRangeMinMaxValue(self, x_range, scale=0.):
"""
获取指定x轴范围内,所有y数据的最大值和最小值
:param x_range: 期望局部放大的x轴范围
:param scale: 将最大值和最小值向两侧延伸一定距离
"""
min_value = np.min([np.min(arr[x_range[0]:x_range[1]]) for arr in self.y])
max_value = np.max([np.max(arr[x_range[0]:x_range[1]]) for arr in self.y])
# 按一定比例缩放
min_value = min_value - (max_value - min_value) * scale
max_value = max_value + (max_value - min_value) * scale
# 返回缩放后的结果
return min_value, max_value
def originPlot(self, fig, **kwargs):
"""
根据 y 数据绘制初始折线图
:param fig: go.Figure实例
"""
fig.add_traces([
go.Scatter(x=self.x, y=arr, opacity=0.7, marker_color=self.colors[i], **kwargs)
for i, arr in enumerate(self.y)
])
return fig
def insetPlot(self, fig, inset_axes):
"""
在原始图像上插入嵌入图
:param fig: go.Figure对象实例
:param inset_axes: 嵌入图的位置和大小 [左下角的x轴位置, 左下角的y轴位置, 宽度, 高度]
所有坐标都是绝对坐标(0~1之间)
"""
# 使用创建子图中的嵌入图参数,创建一个嵌入图
fig = fig.set_subplots(insets=[dict(
type='xy',
l=inset_axes[0], b=inset_axes[1],
w=inset_axes[2], h=inset_axes[3],
)])
# 嵌入图与原始图的绘画一致,需要指定 xaxis 和 yaxis 参数确保是在嵌入图上绘画的
fig = self.originPlot(fig, xaxis='x2', yaxis='y2', showlegend=False)
# 将嵌入图的坐标轴范围限定在指定范围
fig.update_layout(
xaxis2=dict(range=self.x_range),
yaxis2=dict(range=self.y_range)
)
return fig
def rectOriginArea(self, fig):
"""
将放大的区域框起来
:param fig: go.Figure实例
"""
fig.add_trace(go.Scatter(
# 从左上角开始,顺时针连线
x=np.array(self.x_range)[[0, 1, 1, 0, 0]],
y=np.array(self.y_range)[[1, 1, 0, 0, 1]],
mode='lines',
line={'color': '#737473', 'dash': 'dash', 'width': 3},
showlegend=False
))
return fig
def addConnectLine(self, fig, area_point_num, point):
"""
从放大区域指定点连线
:param fig: go.Figure实例
:param area_point_num: 放大区域的锚点,例如:(0, 0)表示放大区域的左下角坐标,(0, 1)表示左上角坐标,
(1, 0)表示右下角坐标,(1, 1)表示右上角坐标,只能取这四种情况
:param point: 要进行连线的另一个点,通常位于嵌入图附近,根据美观程度自行指定
"""
fig.add_shape(type='line',
x0=self.x_range[area_point_num[0]],
y0=self.y_range[area_point_num[1]],
x1=point[0], y1=point[1],
line={'color': '#737473', 'dash': 'dash', 'width': 1},
)
return fig
开始绘制
plot = LocalZoomPlot(x, [y1, y2, y3], ['#f0bc94', '#7fe2b3', '#cba0e6'], (100, 150), 0.)
fig = go.Figure()
fig = plot.originPlot(fig)
fig = plot.insetPlot(fig, (0.4, 0.2, 0.4, 0.3))
fig = plot.rectOriginArea(fig)
fig = plot.addConnectLine(fig, (0, 0), (420, -0.7))
fig = plot.addConnectLine(fig, (1, 1), (900, 2.7))
# 额外对图片进行设置
fig.update_layout(
width=800, height=600,
xaxis=dict(
rangemode='tozero',
showgrid=False,
zeroline=False,
),
xaxis2=dict(
showgrid=False,
zeroline=False
),
)
fig.show()
来源:https://blog.csdn.net/weixin_45826022/article/details/122894413
0
投稿
猜你喜欢
- sql中的 IF 条件语句的用法IF 表达式IF( expr1 , expr2 , expr3 )expr1 的值为 TRUE,则返回值为
- join 方法用于连接字符串数组 s = ['a', 'b', 'c', 'd
- 这是一个给新手学习代码的帖子,包含以下内容:如何使用UBB代码,如何用js与剪贴板交互,如何使用textRange对象,如何使用自定义的快捷
- 如果想读取用 open() 函数打开的文件中的内容,除了可以使用 read() 函数,还可以使用 readline() 和 readline
- 问题背景调试脚本时,遇到一个问题:ImportError: cannot import name 'A' from '
- 到了今天,数据库已经成了网站的灵魂,可以说,没有对数据进行集中管理就算不上是一个真正的网站。而ASP加数据库,更成了主流中的主流,网站里的用
- 什么是 JScript?JScript 是由微软开发的活动脚本语言,基于 ECMAScript 规范实现。Internet Explorer
- 我们经常会遇这样一个需求:判断字符串中是否包含某个关键词,也就是特定的子字符串。比如从一堆书籍名称中找出含有“pytho
- 终于下决心把python从2.7升到了3.7。懒人安装当然使用Anaconda。安装成功,编译成功。但是用pip 安装包的时候提示:pip
- 前言事情是这样的:今天晚上,女朋友让我十二点催她睡觉。不过,可是我实在太困了,熬不下去…… 是吧
- Python2.5之后引入了上下文管理器(context manager),算是Python的黑魔法之一,它用于规定某个对象的使用范围。本文
- 装饰器总结什么是装饰器?处理函数的函数,加一个功能,但是不影响原来函数的内部结构生活中的例子:给手机加一个外壳,外壳保护了手机装饰器有什么用
- 问:我最近升级了一个应用程序,使其可以在 SQL Server 2005 上运行。我利用了允许行长度超出 8,060 个字节这项功能,以便用
- mysql找不到my.ini文件问题描述刚刚在修改mysql默认配置的时候,发现找不到my.ini文件。按照其他搬运工的说法,打开隐藏的文件
- 今天看了篇关于Web Form Design的成功案例,虽然讲的事情很简单,但总结了一些方法,翻译过来做个原始积累吧,以后写东西举例子时也好
- 用python搭建百万答题、自动百度搜索答案。使用平台windows7python3.6MIX2手机代码原理手机屏幕内容同步到pc端对问题截
- python代码换行就是每行后面加个 \举个栗子:time = "2017"print "one"
- SVM支持向量机是建立于统计学习理论上的一种分类算法,适合与处理具备高维特征的数据集。SVM算法的数学原理相对比较复杂,好在由于SVM算法的
- 《Python for Data Analysis》GroupBy分组运算:split-apply-combine(拆分-应用-合并)Dat
- 有的时候取出全部数据库记录也许正好满足你的要求,不过,在大多数情况下我们通常只需得到部分记录。这样一来该如何设计查询呢?当然会更费点脑筋了,