偏移极杆径向原点,python Plotly Express

Offset Polar Bar Radial Origin, python Plotly Express

我正在使用 Plotly Express 生成 WindRose,想知道是否可以偏移径向的起点。

我想要实现的是将 0-2 MPH 风显示为一个圆圈,表示风平浪静,如图 2 所示。

不确定是否可行或如何操作,如有任何帮助,我们将不胜感激。

WindRose generated using Plotly Express

Windrose that I would like to get

fig = px.bar_polar(df, r= "Frequency", theta="Direction",
                   color="Strength", template="none",
                   labels={"Strength": "Wind Speed in MPH"}
                   )

fig.update_layout(legend=dict(
    orientation="h",
    yanchor="top",
    y=-0.1,
    xanchor="center",
    x=0.5),
    polar=dict(radialaxis=dict(showticklabels=False, ticks='', linewidth=0)
    )
)
fig.show()

Direction,Strength,Frequency
N,0-2,1.45
N,2-5,0.4
N,5-7,
N,7-10,
N,10-15,
N,15-20,
NNE,0-2,0.53
NNE,2-5,0.53
NNE,5-7,
NNE,7-10,
NNE,10-15,
NNE,15-20,
NE,0-2,1.06
NE,2-5,
NE,5-7,
NE,7-10,
NE,10-15,
NE,15-20,
ENE,0-2,0.79
ENE,2-5,0.4
ENE,5-7,
ENE,7-10,
ENE,10-15,
ENE,15-20,
E,0-2,1.32
E,2-5,
E,5-7,
E,7-10,
E,10-15,
E,15-20,
ESE,0-2,1.19
ESE,2-5,0.26
ESE,5-7,
ESE,7-10,
ESE,10-15,
ESE,15-20,
SE,0-2,1.72
SE,2-5,1.19
SE,5-7,0.4
SE,7-10,0.13
SE,10-15,
SE,15-20,
SSE,0-2,1.19
SSE,2-5,3.04
SSE,5-7,1.98
SSE,7-10,0.4
SSE,10-15,
SSE,15-20,
S,0-2,1.06
S,2-5,3.17
S,5-7,1.19
S,7-10,
S,10-15,
S,15-20,
SSW,0-2,0.13
SSW,2-5,2.11
SSW,5-7,0.4
SSW,7-10,
SSW,10-15,
SSW,15-20,
SW,0-2,0.79
SW,2-5,0.92
SW,5-7,0.53
SW,7-10,
SW,10-15,
SW,15-20,
WSW,0-2,0.79
WSW,2-5,1.19
WSW,5-7,0.26
WSW,7-10,
WSW,10-15,
WSW,15-20,
W,0-2,0.92
W,2-5,3.83
W,5-7,2.64
W,7-10,0.4
W,10-15,
W,15-20,
WNW,0-2,3.3
WNW,2-5,7.53
WNW,5-7,9.64
WNW,7-10,4.62
WNW,10-15,0.79
WNW,15-20,
NW,0-2,1.72
NW,2-5,10.04
NW,5-7,11.1
NW,7-10,7.4
NW,10-15,1.06
NW,15-20,
NNW,0-2,1.85
NNW,2-5,1.85
NNW,5-7,0.79
NNW,7-10,
NNW,10-15,
NNW,15-20,

由于似乎没有办法调整 Plotly 中 bar_polar 绘图的起始半径值,因此最好的办法是尝试找到一些解决方法。

诚然,这是一个 非常 的解决方案,但为了确保图表不会太接近原点,我们可以创建一个 New_Frequency 列,简单地将任意值添加到 Frequency 列。我选择了 30。请注意,这样做会扭曲条形之间的相对距离(如果这是一个问题,则需要以某种方式修改解决方案)。

然后我们将bar_polar方法中的参数r设置为这个新的列,并修改悬停数据,使其显示原来的Frequency列。

现在我们可以画一个圆圈,上面写着“平静”,它覆盖了 0-2 MPH 值对应的内条。添加形状时,尽管这是极坐标图,但您需要指定笛卡尔坐标。经过反复试验,似乎 x=0.5, y=0.5 是 bar_polar 图的中心,从 x0=0.4, y0=0.4, x1=0.6, y1=0.6 开始的圆圈覆盖内部酒吧。不知道有没有这方面的文档。

如果您只是追求图像,那么希望它看起来不错。请注意,切换图例中的不同风速会扭曲情节,圆圈将不再覆盖内部条形图,因此您会失去一些情节的互动性。

我已经包含了下面的代码:

import pandas as pd
import plotly.express as px
import plotly.graph_objects as go

df = pd.read_csv("windrose.csv")

## this adds 30 to all frequencies, so 0-2 becomes 30-32
df["New_Frequency"] = df["Frequency"] + 30

fig = px.bar_polar(df, r="New_Frequency", theta="Direction",
                   color="Strength", template="none",
                   labels={"Strength": "Wind Speed in MPH"},
                   hover_data={"Strength":True, "New_Frequency":False, "Frequency":True ,"Direction":True}
                   )

fig.add_shape(
    type="circle",
            xref="paper",
            yref="paper",
            x0=0.4,
            y0=0.4,
            x1=0.6,
            y1=0.6,
            line_color="Black",
            fillcolor="White",
            # text="Calm"
)

fig.add_annotation( # add a text callout with arrow
    text="Calm", x=0.5, y=0.5, showarrow=False
)

fig.update_layout(width=800, height=800)
fig.update_layout(legend=dict(
    orientation="h",
    yanchor="top",
    y=-0.1,
    xanchor="center",
    x=0.5),
    polar=dict(radialaxis=dict(showticklabels=False, ticks='', linewidth=0)
    )
)
fig.show()

我找到了另一种在极坐标条形图中间添加圆的解决方案,方法是在 update_layout 中使用“孔”。代码附在下面:

fig2 = px.bar_polar(df, r="Frequency", theta="Direction",
                    color="Strength", template="none",
                    labels={"Strength": "Wind Speed <br>&nbsp;&nbsp;&nbsp; in MPH:"
                            }
                    )

fig2.add_annotation(
    text="Calm<br>" + " " + percent + "%", x=0.5, y=0.5, showarrow=False
)

fig2.add_annotation(
    text="Calm Values are for <br> Wind Speed <2.0 MPH <br />", x=0.93, y=-0.13, showarrow=False
)

fig2.update_layout(legend=dict(
    orientation="h",
    yanchor="middle",  
    y=-0.1,
    xanchor="center",
    x=0.5,
    font=dict(
        size=14)),
    polar=dict(hole=0.1, radialaxis=dict(showticklabels=False, ticks='', linewidth=0)
               ),
    margin=dict(t=110),
    title=dict(
        text=title,
        xanchor='center',
        yanchor='top'
    )
)

输出:

由于 0-2 MPH 在中间显示为一个圆圈,在我的数据框中我将所有 0-2 MPH 的值设置为零,这确保了 0-2 bins 不显示。