我正在尝试向极坐标图添加注释箭头,但这会产生另一个底层笛卡尔图:
问题1:有没有办法为极坐标图添加注释? 2019年的这一页表明不是,这仍然是当前状态吗?:https://community.plotly.com/t/adding-annotations-to-polar-scatterplots/704
问题 2: 有没有办法在极坐标图上生成箭头? (隐藏对齐的覆盖透明笛卡尔图?在极坐标图中用线条低水平绘制箭头?)
生成上图的代码在这里:
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
df = pd.DataFrame()
fig = px.scatter_polar(
df,
theta=None,
r=None,
range_theta=[-180, 180],
start_angle=0,
direction="counterclockwise",
template="plotly_white",
)
x_end = [1, 2, 2]
y_end = [3, 5, 4]
x_start = [0, 1, 3]
y_start = [4, 4, 4]
list_of_all_arrows = []
for x0, y0, x1, y1 in zip(x_end, y_end, x_start, y_start):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5,
arrowcolor='rgb(255,51,0)', )
)
list_of_all_arrows.append(arrow)
fig.update_layout(annotations=list_of_all_arrows)
fig.show()
编辑:
这是我编码的内容。
# Import modules
import numpy as np
import matplotlib.pyplot as plt
# ------------------------------------ #
# Define the figure
fig = plt.figure(figsize=(16,16))
# Setting the axes projection as polar
ax = fig.add_subplot(111, projection='polar')
# List of angles to put the arrows
thetas = [30.0, 10.0, -20.0]
# List that stores the color of each arrow
colors = ["yellow", "cyan", "blue"]
# Iterate through the list
for i in range(len(thetas)):
# Convert to radians
theta = np.deg2rad(thetas[i])
# Draw the arrow
#
# plt.arrow(theta_b, r_b, theta_e, r_e)
# The polar coordinates of the beginning point of arrow is (theta_b, r_b)
# The polar coordinates of the end point of arrow is (theta_a, r_a)
#
# These values that I have set so that the arrow points towards the center
# as you requested. You can play with them to obtain different results.
#
plt.arrow(theta, 0.1, 0.0, -0.25, \
width=0.015, lw=3, head_width=0.4, \
head_length=0.02, color=colors[i], ec=colors[i])
# Annotate does not work. You can use text though
# plt.text(np.pi/6.0, 0.02, "Text")
# Remove tick labels
ax.set_xticklabels([])
ax.set_yticklabels([])
# Display the plot
plt.show()
我希望我已经回答了你的问题。
由于似乎仍然无法向极坐标图添加注释,因此我自己使用隐藏的真正散点图(笛卡尔网格)进行了操作,在其上绘制了线来表示极坐标网格。
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
def polar2z(r, theta):
# theta is given in trigo convention, from 0° = X axis
imZ = np.array(r) * np.exp(1j * np.array(theta))
return np.real(imZ), np.imag(imZ)
def polar_graph_with_arrows(r_max, r_min, theta, colors):
df = pd.DataFrame()
figDLC = px.scatter(
df,
x=None,
y=None,
template="plotly_white")
rm_max = 1.1 # margin radius
# --- Draw polar grid ---
# radial grid and labels
list_of_labels = []
figDLC.update_layout(margin=dict(l=10, r=10, b=10, t=40)) # https://stackoverflow.com/questions/60913366/how-to-annotate-a-point-outside-the-plot-itself
for t in np.arange(0, 360, 30):
x_min, y_min = 0, 0
x_max, y_max = polar2z(1, t * np.pi / 180.)
figDLC.add_trace(go.Scatter(
x=[x_min, x_max],
y=[y_min, y_max],
mode='lines',
name='_',
line={'width': 1},
line_color='LightGrey',
hoverinfo='skip'))
offsetx, offsety = polar2z(rm_max, t * np.pi / 180.) # radial offset of 0.05
label_t = "{:d}°".format(np.mod(t+180, 360) - 180) # set t between [-180, 180[
label = go.layout.Annotation(dict(
text=label_t,
xref="x", yref="y", # axes-positioned annotation
font=dict(color="black", size=12),
x=offsetx, y=offsety, showarrow=False))
list_of_labels.append(label)
# circles grid
t = np.arange(0, 360 + 5, 5)
# secondary lines
for r in np.arange(0, 1 + 0.25, 0.25):
x, y = polar2z(r, t * np.pi / 180.)
figDLC.add_trace(go.Scatter(
x=x,
y=y,
mode='lines',
name='_',
line={'width': 1},
line_color='LightGrey',
hoverinfo='skip'))
# secondary lines
for r in np.arange(0, 1 + 0.25, 0.25):
x, y = polar2z(r, t * np.pi / 180.)
figDLC.add_trace(go.Scatter(
x=x,
y=y,
mode='lines',
name='_',
line={'width': 1},
line_color='LightGrey',
hoverinfo='skip'))
# --- add arrows ---
list_of_all_arrows = []
# theta shall be given in trigo convention, from 0° = X axis
x_min, y_min = polar2z(r_min, theta * np.pi / 180.)
x_max, y_max = polar2z(r_max, theta * np.pi / 180.)
for x0, y0, x1, y1, theta, color, name in zip(x_min, y_min, x_max, y_max, t, colors, r_max):
arrow = go.layout.Annotation(dict(
x=x0,
y=y0,
xref="x", yref="y",
text="",
name=name,
showarrow=True,
axref="x", ayref='y',
ax=x1,
ay=y1,
arrowhead=3,
arrowwidth=1.5 * 2,
arrowcolor=str(color),
)
)
list_of_all_arrows.append(arrow)
# update custom data depending on frame
theta_cd = theta
# add a single point marker to get hover info
figDLC.add_trace(go.Scatter(
x=[x1],
y=[y1],
name=name,
marker={'color': str(color), 'size': 12},
customdata=np.stack(([theta_cd], [name]), axis=-1),
hovertemplate="<br>".join([
"dir: %{customdata[0]:d}°",
"r: %{customdata[1]}"])
))
figDLC.update_layout(hovermode='closest', # default, may be "x" | "y" | "closest" | False | "x unified" | "y unified"
hoverdistance=100) # default 20 (px), distance at which points are detected
# switch off real cartesian axes
figDLC.update_xaxes(showgrid=False, zerolinecolor='LightGrey', visible=False)
figDLC.update_yaxes(showgrid=False, zerolinecolor='LightGrey', visible=False)
figDLC.update_layout(
title="Polar arrows",
showlegend=False
)
figDLC.update_yaxes(
scaleanchor="x",
scaleratio=1,
range=(-rm_max, rm_max),
constrain='domain'
)
figDLC.update_xaxes(
range=(-rm_max, rm_max),
constrain='domain'
)
figDLC.update_layout(annotations=list_of_labels + list_of_all_arrows)
return figDLC
if __name__ == "__main__":
# user parameters for 3 arrows:
r_max = np.array([0.5, 0.7, 0.9]) # radius of arrow start
r_min = 0.025 # radius of arrow tip:
# -r_max for an arrow going through the center,
# - 0.025 (or any small value) for an arrow pointing to the center
theta = np.array([15, 20, 35]) # orientation in degrees
colors = ['Gold', 'deepskyblue', 'DarkBlue'] # colors may also be in rgb: 'rgb(51,255,51)'
fig = polar_graph_with_arrows(r_max, r_min, theta, colors)
fig.show()
奖励中,将鼠标悬停在箭头开始处可提供有关数据的更多信息。