2020 年 5 月,Alexandre Morin-Chassé 发表了一篇关于星图的博客文章。这种类型的图表是雷达图(也称为网络图、蜘蛛图、星图或蛛网图)的(大约)直接替代品- 您可以在此处阅读有关此图表的更多信息。
在本教程中,我们将看到如何创建一个快速而肮脏的恒星图表。首先,让我们获得必要的模块/库,并准备一个虚拟数据集(只有一个记录)。
from itertools import chain, zip_longest
from math import ceil, pi
import matplotlib.pyplot as plt
data = [
("V1", 8),
("V2", 10),
("V3", 9),
("V4", 12),
("V5", 6),
("V6", 14),
("V7", 15),
("V8", 25),
]
我们还需要一些辅助函数,即一个向上取整到最近 10round_up()
的函数( ) 和一个连接两个序列的函数 ( even_odd_merge()
)。在后者中,第一个序列(基本上是列表或元组)的值将填充偶数位置,而第二个序列的值将填充奇数位置。
def round_up(value):
"""
>>> round_up(25)
30
"""
return int(ceil(value / 10.0)) * 10
def even_odd_merge(even, odd, filter_none=True):
"""
>>> list(even_odd_merge([1,3], [2,4]))
[1, 2, 3, 4]
"""
if filter_none:
return filter(None.__ne__, chain.from_iterable(zip_longest(even, odd)))
return chain.from_iterable(zip_longest(even, odd))
也就是说,要data
在星图上绘图,我们需要应用一些变换,并计算一些辅助值。因此,让我们首先创建一个函数 ( prepare_angles()
) 来计算图表上每个轴的角度(N
对应于要绘制的变量数量)。
def prepare_angles(N):
angles = [n / N * 2 * pi for n in range(N)]
# Repeat the first angle to close the circle
angles += angles[:1]
return angles
接下来,我们需要一个函数(prepare_data()
)负责调整原始数据(data
)并将其分成几个易于使用的对象。
def prepare_data(data):
labels = [d[0] for d in data] # Variable names
values = [d[1] for d in data]
# Repeat the first value to close the circle
values += values[:1]
N = len(labels)
angles = prepare_angles(N)
return labels, values, angles, N
最后,对于图表的这种特定类型的,我们需要一个函数(prepare_stellar_aux_data()
),从先前计算出的角度,准备辅助值的两个列表:列表中间角度(对于每对角度stellar_angles
)和小的列表的恒定值(stellar_values
),它将作为要绘制的变量值,以实现星图的星状形状。
def prepare_stellar_aux_data(angles, ymax, N):
angle_midpoint = pi / N
stellar_angles = [angle + angle_midpoint for angle in angles[:-1]]
stellar_values = [0.05 * ymax] * N
return stellar_angles, stellar_values
在这一点上,我们已经有了恒星图的所有必要成分,所以让我们继续本教程的 Matplotlib 方面。在美学方面,我们可以依靠draw_peripherals()
为此特定目的而设计的函数 ( )(随意定制它!)。
def draw_peripherals(ax, labels, angles, ymax, outer_color, inner_color):
# X-axis
ax.set_xticks(angles[:-1])
ax.set_xticklabels(labels, color=outer_color, size=8)
# Y-axis
ax.set_yticks(range(10, ymax, 10))
ax.set_yticklabels(range(10, ymax, 10), color=inner_color, size=7)
ax.set_ylim(0, ymax)
ax.set_rlabel_position(0)
# Both axes
ax.set_axisbelow(True)
# Boundary line
ax.spines["polar"].set_color(outer_color)
# Grid lines
ax.xaxis.grid(True, color=inner_color, linestyle="-")
ax.yaxis.grid(True, color=inner_color, linestyle="-")
要绘制数据并编排(几乎)拥有恒星图所需的所有步骤,我们只需要最后一个函数:draw_stellar()
.
def draw_stellar( ax, labels, values, angles, N, shape_color="tab:blue", outer_color="slategrey", inner_color="lightgrey", ):
# Limit the Y-axis according to the data to be plotted
ymax = round_up(max(values))
# Get the lists of angles and variable values
# with the necessary auxiliary values injected
stellar_angles, stellar_values = prepare_stellar_aux_data(angles, ymax, N)
all_angles = list(even_odd_merge(angles, stellar_angles))
all_values = list(even_odd_merge(values, stellar_values))
# Apply the desired style to the figure elements
draw_peripherals(ax, labels, angles, ymax, outer_color, inner_color)
# Draw (and fill) the star-shaped outer line/area
ax.plot(
all_angles,
all_values,
linewidth=1,
linestyle="solid",
solid_joinstyle="round",
color=shape_color,
)
ax.fill(all_angles, all_values, shape_color)
# Add a small hole in the center of the chart
ax.plot(0, 0, marker="o", color="white", markersize=3)
最后,让我们在空白画布上绘制图表(图)。
fig = plt.figure(dpi=100)
ax = fig.add_subplot(111, polar=True) # Don't forget the projection!
draw_stellar(ax, *prepare_data(data))
plt.show()
完成!现在,您有一个恒星图表示例和用于将此类图表添加到您的曲目的样板代码。如果您最终创建了自己的星图,请随时与世界(还有我!)分享它们。我希望本教程对您有用且有趣!