python用plotly实现绘制局部放大图
更新时间:2022年02月13日 11:17:56 作者:Eloik
大家好,本篇文章主要讲的是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()
总结
到此这篇关于python用plotly实现绘制局部放大图的文章就介绍到这了,更多相关python plotly绘制局部放大图内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
关于Qt6中QtMultimedia多媒体模块的重大改变分析
如果您一直在 Qt 5 中使用 Qt Multimedia,则需要对您的实现进行更改。这篇博文将尝试引导您完成最大的变化,同时查看 API 和内部结构2021-09-09Python图像处理之图像的读取、显示与保存操作【测试可用】
这篇文章主要介绍了Python图像处理之图像的读取、显示与保存操作,结合实例形式分析了Python使用PIL模块、scipy和matplotlib模块进行图像读写、显示等相关操作技巧,需要的朋友可以参考下2019-01-01Python的Flask框架应用调用Redis队列数据的方法
这里为大家带来Python的Flask框架应用调用Redis队列数据的方法,从而能够实现异步无阻塞从而提高某些实时处理情况下程序的性能,需要的朋友可以参考下2016-06-06使用Keras中的ImageDataGenerator进行批次读图方式
这篇文章主要介绍了使用Keras中的ImageDataGenerator进行批次读图方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2020-06-06
最新评论