Python 绘制极坐标图切片对齐
Python Plotly Polar Chart Slice Alignment
所以我想做的是使用 plotly 创建一个极坐标图。但是,它需要看起来类似于饼图,其中每个 label
都被赋予了圆的一部分。目前,如果我将圆分成相等的切片,极坐标图工作正常。但是,当我尝试给他们一个对应于 weights
的切片时,效果不太好,因为它往往会重叠或在每个切片之间留出空间。这主要是由于Theta。
谁能解释一下我哪里出错了?
Ratings
- 最大值为5,最小值为1。用于确定极坐标图中切片的长度。
Weights
- 最大值为100,最小值为1。用于确定极坐标图中切片的宽度。
Labels
- 识别每个切片。
等分圆时
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 58]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
num_slices = len(weights)
theta = [(i) * 360 / num_slices for i in range(0, num_slices)]
width = [360 / num_slices for _ in range(num_slices)]
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
Polar Chart 1
当使用weights
计算宽度和theta时
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 38]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
angles = [(weight / sum(weights) * 360) for weight in weights]
theta = []
num_slices = len(ratings)
theta = []
for index, angle in enumerate(angles):
if index < len(angles)-1:
if index == 0:
theta.append(0)
theta.append(theta[index] + angle)
width = angles
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
Polar Chart 2
我认为您假设 theta
设置径向扇区的一个边缘的位置,而实际上它是该径向扇区的 中心 。这是您的代码,但计算了 theta
来解释这种差异:
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 38]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
angles = [(weight / sum(weights) * 360) for weight in weights]
num_slices = len(ratings)
theta = [0.5 * angle for angle in angles]
for index, angle in enumerate(angles):
for subsequent_index in range(index + 1, len(angles)):
theta[subsequent_index] += angle
width = angles
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
这给出了
如果您想将所有内容移回原位,使浅蓝色扇区直接指向右侧,您可以随时从 theta
的每个元素中减去 0.5 * angle[0]
作为一个额外的小步骤。
__
P.S。非常高质量 post 第一次 poster。太棒了!
所以我想做的是使用 plotly 创建一个极坐标图。但是,它需要看起来类似于饼图,其中每个 label
都被赋予了圆的一部分。目前,如果我将圆分成相等的切片,极坐标图工作正常。但是,当我尝试给他们一个对应于 weights
的切片时,效果不太好,因为它往往会重叠或在每个切片之间留出空间。这主要是由于Theta。
谁能解释一下我哪里出错了?
Ratings
- 最大值为5,最小值为1。用于确定极坐标图中切片的长度。
Weights
- 最大值为100,最小值为1。用于确定极坐标图中切片的宽度。
Labels
- 识别每个切片。
等分圆时
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 58]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
num_slices = len(weights)
theta = [(i) * 360 / num_slices for i in range(0, num_slices)]
width = [360 / num_slices for _ in range(num_slices)]
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
Polar Chart 1
当使用weights
计算宽度和theta时
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 38]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
angles = [(weight / sum(weights) * 360) for weight in weights]
theta = []
num_slices = len(ratings)
theta = []
for index, angle in enumerate(angles):
if index < len(angles)-1:
if index == 0:
theta.append(0)
theta.append(theta[index] + angle)
width = angles
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
Polar Chart 2
我认为您假设 theta
设置径向扇区的一个边缘的位置,而实际上它是该径向扇区的 中心 。这是您的代码,但计算了 theta
来解释这种差异:
import plotly.graph_objects as go
import plotly.express as px
ratings = [3, 2, 5, 1, 2]
weights = [65, 79, 81, 98, 38]
labels = ["Strength", "Intelligence", "Dexterity", "Wisdom", "Stealth"]
def make_barpolar(ratings, weights, labels=None, colors=None, layout_options = None, **fig_kwargs):
# infer slice angles
angles = [(weight / sum(weights) * 360) for weight in weights]
num_slices = len(ratings)
theta = [0.5 * angle for angle in angles]
for index, angle in enumerate(angles):
for subsequent_index in range(index + 1, len(angles)):
theta[subsequent_index] += angle
width = angles
# optionally infer colors
if colors is None:
color_seq = px.colors.qualitative.Safe
color_indices = range(0, len(color_seq), len(color_seq) // num_slices)
colors = [color_seq[i] for i in color_indices]
if layout_options is None:
layout_options = {}
if labels is None:
labels = ["" for _ in range(num_slices)]
layout_options["showlegend"] = False
# make figure
barpolar_plots = [go.Barpolar(r=[r], theta=[t], width=[w], name=n, marker_color=[c], **fig_kwargs)
for r, t, w, n, c in zip(ratings, theta, width, labels, colors)]
fig = go.Figure(barpolar_plots)
# additional layout parameters
fig.update_layout(**layout_options)
return fig
layout_options = {"title": "My Stats",
"title_font_size": 24,
"title_x": 0.5,
"legend_x": 0.85,
"legend_y": 0.5,
"polar_radialaxis_ticks": "",
"polar_radialaxis_showticklabels": False,
"polar_radialaxis_range": [0, max(ratings)],
"polar_angularaxis_ticks": "",
"polar_angularaxis_showticklabels": False}
fig = make_barpolar(ratings, weights, labels, layout_options=layout_options, opacity = 0.7)
fig.show()
这给出了
如果您想将所有内容移回原位,使浅蓝色扇区直接指向右侧,您可以随时从 theta
的每个元素中减去 0.5 * angle[0]
作为一个额外的小步骤。
__
P.S。非常高质量 post 第一次 poster。太棒了!