极坐标图中的注释

问题描述 投票:0回答:2

我正在尝试向极坐标图添加注释箭头,但这会产生另一个底层笛卡尔图:

问题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()

编辑:

总之,我想要类似的东西,带有与极坐标图相关的注释:

python plotly polar-coordinates polar-plot
2个回答
0
投票

这是我编码的内容。

# 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()

这产生,

我希望我已经回答了你的问题。


0
投票

由于似乎仍然无法向极坐标图添加注释,因此我自己使用隐藏的真正散点图(笛卡尔网格)进行了操作,在其上绘制了线来表示极坐标网格。

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()

这显示了想要的:

奖励中,将鼠标悬停在箭头开始处可提供有关数据的更多信息。

© www.soinside.com 2019 - 2024. All rights reserved.