python - 用于绘图指标图的仪表针
问题描述
我目前有一个来自 plotly 的指标图表(仪表),其中的值显示为深蓝色中心到达的距离。然而,这对我来说有点奇怪,所以我想把它改成从中心到值的指针/指针,就像速度表一样。这是我当前的代码:
import plotly.graph_objects as go
fig = go.Figure(go.Indicator(
mode = "gauge+number",
number = {'suffix': "% match", 'font': {'size': 50}},
value = 80,
domain = {'x': [0,1], 'y': [0,1]},
gauge = {
'axis': {'range': [None, 100], 'tickwidth': 1, 'tickcolor': "darkblue"},
'bar': {'color': "darkblue"},
'bgcolor': "white",
'borderwidth': 2,
'bordercolor': "gray",
'steps': [
{'range': [0, 33], 'color': 'red'},
{'range': [33, 66], 'color': 'yellow'},
{'range': [66,100], 'color': 'green'}],
}))
fig.update_layout(font = {'color': "black", 'family': "Arial"})
fig.show()
解决方案
我的建议是添加一个覆盖指标图表的箭头注释。
通过将图表的范围设置为 [-1,1] x [0,1],我们基本上是在创建一个箭头所在的新坐标系,我们可以估计箭头应该指向的位置以对应于指标图表上的值。这也将确保点 (0,0) 位于图表的中心,这很方便,因为这将是箭头的端点之一。
添加箭头注释时ax
,并且ay
是箭头尾部的坐标,因此我们希望它位于图表中间,位于ax=0
和处ay=0
。我将箭头笔直向上放置,以显示指标图表相对于图表的半径对于我的浏览器窗口约为 0.9 个单位。这对你来说可能会有所不同。
import plotly.graph_objects as go
fig = go.Figure(go.Indicator(
mode = "gauge+number",
number = {'suffix': "% match", 'font': {'size': 50}},
value = 80,
domain = {'x': [0,1], 'y': [0,1]},
gauge = {
'axis': {'range': [None, 100], 'tickwidth': 1, 'tickcolor': "darkblue"},
'bar': {'color': "darkblue"},
'bgcolor': "white",
'borderwidth': 2,
'bordercolor': "gray",
'steps': [
{'range': [0, 33], 'color': 'red'},
{'range': [33, 66], 'color': 'yellow'},
{'range': [66,100], 'color': 'green'}],
}))
fig.update_layout(
font={'color': "black", 'family': "Arial"},
xaxis={'showgrid': False, 'range':[-1,1]},
yaxis={'showgrid': False, 'range':[0,1]},
# plot_bgcolor='rgba(0,0,0,0)'
)
## by setting the range of the layout, we are effectively adding a grid in the background
## and the radius of the gauge diagram is roughly 0.9 when the grid has a range of [-1,1]x[0,1]
fig.add_annotation(
ax=0,
ay=0,
axref='x',
ayref='y',
x=0,
y=0.9,
xref='x',
yref='y',
showarrow=True,
arrowhead=3,
arrowsize=1,
arrowwidth=4
)
fig.show()
现在,虽然我们可以使用反复试验来找到箭头应该在哪里结束,但这是一个真正的 hacky 解决方案,根本无法推广。
对于接下来的步骤,我建议您为浏览器窗口大小选择一个纵横比,以使指标图表尽可能接近圆形(例如,极端纵横比将使您的指标图表更椭圆,我正在制作一个简单的假设指标图表是一个完美的圆)。
因此,假设指标图表大致是一个半径 ≈ 0.9 的圆(在我的情况下,您的半径可能不同),我们可以使用极坐标找到您的圆的 x 和 y 坐标:x = r*cos(θ)
和y = r*sin(θ)
。请注意,此公式仅对以 (0,0) 为中心的圆有效,这就是我们将图表居中的原因。
由于指标上的值是 0-100 范围内的 80,我们是 180 旋转角度的 80/100,得出180 degrees*(80/100) = 144 degrees
. 所以你从左下角顺时针旋转 144 度,或者从右下角逆时针旋转 36 度。
插入电源,我们得到x = 0.9*cos(36 degrees) = 0.72811529493
和y = 0.9*sin(36 degrees) = 0.52900672706
。更新注释:
fig.add_annotation(
ax=0,
ay=0,
axref='x',
ayref='y',
x=0.72811529493,
y=0.52900672706,
xref='x',
yref='y',
showarrow=True,
arrowhead=3,
arrowsize=1,
arrowwidth=4
)
我们得到以下图像:
所以这是非常接近的,但不是一门精确的科学。对于我的浏览器窗口,让我们将角度稍微调高到 40 度。重复相同的过程x = 0.9*cos(40 degrees) = 0.6894399988
, 和y = 0.9*cos(40 degrees) = 0.57850884871
, 并更新注释坐标,我得到以下图表:
为了使图表更漂亮,我们现在可以删除图表的刻度标签以进行箭头注释,并使背景透明。并且为了让这个方法更容易调整,我做了theta
和r
变量。
from numpy import radians, cos, sin
import plotly.graph_objects as go
fig = go.Figure(go.Indicator(
mode = "gauge+number",
number = {'suffix': "% match", 'font': {'size': 50}},
value = 80,
domain = {'x': [0,1], 'y': [0,1]},
gauge = {
'axis': {'range': [None, 100], 'tickwidth': 1, 'tickcolor': "darkblue"},
'bar': {'color': "darkblue"},
'bgcolor': "white",
'borderwidth': 2,
'bordercolor': "gray",
'steps': [
{'range': [0, 33], 'color': 'red'},
{'range': [33, 66], 'color': 'yellow'},
{'range': [66,100], 'color': 'green'}],
}))
fig.update_layout(
font={'color': "black", 'family': "Arial"},
xaxis={'showgrid': False, 'showticklabels':False, 'range':[-1,1]},
yaxis={'showgrid': False, 'showticklabels':False, 'range':[0,1]},
plot_bgcolor='rgba(0,0,0,0)'
)
## by setting the range of the layout, we are effectively adding a grid in the background
## and the radius of the gauge diagram is roughly 0.9 when the grid has a range of [-1,1]x[0,1]
theta = 40
r= 0.9
x_head = r * cos(radians(theta))
y_head = r * sin(radians(theta))
fig.add_annotation(
ax=0,
ay=0,
axref='x',
ayref='y',
x=x_head,
y=y_head,
xref='x',
yref='y',
showarrow=True,
arrowhead=3,
arrowsize=1,
arrowwidth=4
)
fig.show()
推荐阅读
- c# - C# WPF 与 CLR 抛出异常
- json - 动态标记和 infoWindow Google Maps API 使用 Google App Engine 通过 JSON 文件解析
- java - 在波纹管项目的顶部项目上显示计算结果
- javascript - 如何在不使用 axios 崩溃功能的情况下处理错误?
- http - IdHttpServer 不提供文件
- python - 如何在推理期间清除变量以释放 ram 内存?
- javascript - 在滚动时执行 addClass 或 removeClass 时如何添加淡入淡出或淡出动画
- c++ - 每次调用函数时进行静态对象初始化
- excel - 如何在特定范围内获得小值
- python - Django 在模板中显示图像和图像文件名