import matplotlib.pyplot as plt
import numpy as np
from matplotlib.lines import Line2D
from palmerpenguins import load_penguins
以下数据如果有需要的同学可关注公众号HsuHeinrich,回复【数据可视化】自动获取~
penguins = load_penguins()
penguins.head()

image-20240129174524839
species:企鹅的种类,包括 Adelie、Chinstrap 和 Gentoo 三种。 island:企鹅所在岛屿的名字,包括 Biscoe、Dream 和 Torgersen 三个岛屿。 bill_length_mm:企鹅的喙长,单位毫米。 bill_depth_mm:企鹅的喙深,单位毫米。 flipper_length_mm:企鹅的鳍长,单位毫米。 body_mass_g:企鹅的体重,单位克。 sex:企鹅的性别,包括 Male 和 Female。
# 清洗na
penguins = penguins.dropna()
# 数据缩放
def rescale(x):
return (x - np.min(x)) / np.ptp(x)
penguins_radar = (
penguins.groupby('species').agg(
avg_bill_length = ("bill_length_mm", np.mean),
avg_bill_depth = ("bill_depth_mm", np.mean),
avg_flipper_length = ("flipper_length_mm", np.mean),
avg_body_mass = ("body_mass_g", np.mean)
)
.apply(lambda x: rescale(x))
.reset_index()
)
penguins_radar

image-20240129174548878
# 自定义颜色
BG_WHITE = "#fbf9f4"
BLUE = "#2a475e"
GREY70 = "#b3b3b3"
GREY_LIGHT = "#f2efe8"
COLORS = ["#FF5A5F", "#FFB400", "#007A87"]
# 初始化定义变量
# 物种
SPECIES = penguins_radar["species"].values.tolist()
# 变量
VARIABLES = penguins_radar.columns.tolist()[1:]
VARIABLES_N = len(VARIABLES)
# 角度
ANGLES = [n / VARIABLES_N * 2 * np.pi for n in range(VARIABLES_N)]
ANGLES += ANGLES[:1]
# 标签刻度
X_VERTICAL_TICK_PADDING = 5
X_HORIZONTAL_TICK_PADDING = 50
# 角度刻度
HANGLES = np.linspace(0, 2 * np.pi)
# 用于绘制自定义线(类似于水平线)
H0 = np.zeros(len(HANGLES))
H1 = np.ones(len(HANGLES)) * 0.5
H2 = np.ones(len(HANGLES))
# 初始化布局
fig = plt.figure(figsize=(14, 10))
ax = fig.add_subplot(111, polar=True)
fig.patch.set_facecolor(BG_WHITE)
ax.set_facecolor(BG_WHITE)
# 偏移至顶部
ax.set_theta_offset(np.pi / 2)
ax.set_theta_direction(-1)
# y轴范围
ax.set_ylim(-0.1, 1.05)
# 绘制每个物种的雷达图
for idx, species in enumerate(SPECIES):
values = penguins_radar.iloc[idx].drop("species").values.tolist()
values += values[:1]
ax.plot(ANGLES, values, c=COLORS[idx], linewidth=4, label=species)
ax.scatter(ANGLES, values, s=160, c=COLORS[idx], zorder=10)

output_10_0
# x刻度与标签
ax.set_xticks(ANGLES[:-1])
ax.set_xticklabels(VARIABLES, size=14)
# 移除网格线
ax.set_yticks([])
ax.yaxis.grid(False)
ax.xaxis.grid(False)
# 移除边框
ax.spines["start"].set_color("none")
ax.spines["polar"].set_color("none")
# 添加自定义虚线(圆)
ax.plot(HANGLES, H0, ls=(0, (6, 6)), c=GREY70)
ax.plot(HANGLES, H1, ls=(0, (6, 6)), c=COLORS[2])
ax.plot(HANGLES, H2, ls=(0, (6, 6)), c=GREY70)
# 填充背景
ax.fill(HANGLES, H2, GREY_LIGHT)
# 自定义水平/垂直线
ax.plot([0, 0], [0, 1], lw=2, c=GREY70)
ax.plot([np.pi, np.pi], [0, 1], lw=2, c=GREY70)
ax.plot([np.pi / 2, np.pi / 2], [0, 1], lw=2, c=GREY70)
ax.plot([-np.pi / 2, -np.pi / 2], [0, 1], lw=2, c=GREY70)
# 添加注释
PAD = 0.05
ax.text(-0.4, 0 + PAD, "0%", size=16, fontname="Roboto")
ax.text(-0.4, 0.5 + PAD, "50%", size=16, fontname="Roboto")
ax.text(-0.4, 1 + PAD, "100%", size=16, fontname="Roboto")
fig

output_12_0
# 生成图例
handles = [
Line2D(
[], [],
c=color,
lw=3,
marker="o",
markersize=8,
label=species
)
for species, color in zip(SPECIES, COLORS)
]
legend = ax.legend(
handles=handles,
loc=(1, 0), # 位于右下角
labelspacing=1.5,
frameon=False
)
# 修改图例字体
for text in legend.get_texts():
text.set_fontname("Roboto")
text.set_fontsize(16)
# 调整刻度位置
XTICKS = ax.xaxis.get_major_ticks()
for tick in XTICKS[0::2]:
tick.set_pad(X_VERTICAL_TICK_PADDING)
for tick in XTICKS[1::2]:
tick.set_pad(X_HORIZONTAL_TICK_PADDING)
# 添加标题
fig.suptitle(
"Radar Plot of Penguin Species",
x = 0.1,
y = 1,
ha="left",
fontsize=32,
fontname="Lobster Two",
color=BLUE,
weight="bold",
)
fig

参考:Radar chart with Matplotlib[1]
共勉~
[1]
Radar chart with Matplotlib: https://python-graph-gallery.com/web-radar-chart-with-matplotlib/