119 lines
3.7 KiB
Python
119 lines
3.7 KiB
Python
from io import BytesIO
|
||
|
||
import numpy as np
|
||
import matplotlib.pyplot as plt
|
||
import pandas as pd
|
||
|
||
|
||
class Radar(object):
|
||
|
||
def __init__(self, figure, title, labels, epoch, rect=None):
|
||
if rect is None:
|
||
rect = [0.1, 0.05, 0.75, 0.9]
|
||
|
||
self.n = len(title)
|
||
self.angles = np.arange(0, 360, 360.0 / self.n)
|
||
self.labels = labels
|
||
|
||
self.axes = [figure.add_axes(rect, projection='polar', label='axes%d' % i) for i in range(self.n)]
|
||
|
||
self.ax = self.axes[0]
|
||
self.ax.set_thetagrids(self.angles, labels=title, fontsize=12)
|
||
self.ax.xaxis.set_tick_params(pad=22) # Increase padding to move labels outward
|
||
|
||
for ax in self.axes[1:]:
|
||
ax.patch.set_visible(False)
|
||
ax.grid(False)
|
||
ax.xaxis.set_visible(False)
|
||
|
||
for ax, angle, label, i in zip(self.axes, self.angles, labels, epoch):
|
||
ax.set_rgrids(i[1:], angle=angle, labels=label)
|
||
ax.spines['polar'].set_visible(False)
|
||
ax.set_ylim(i[0], i[-1])
|
||
|
||
def plot(self, values, *args, **kw):
|
||
angle = np.deg2rad(np.r_[self.angles, self.angles[0]])
|
||
|
||
# 第一个值保持不变
|
||
adjusted_values = [values[0]]
|
||
|
||
# 获取 labels 对应的最后一位的差值
|
||
base_last_value = float(self.labels[0][-1]) # 第一个 labels 列表的最后一位
|
||
|
||
# 计算新的 values
|
||
for i in range(1, len(values)):
|
||
current_label_last_value = float(self.labels[i][-1]) # 当前 labels 列表的最后一位
|
||
difference = current_label_last_value - base_last_value
|
||
adjusted_value = values[i] - difference
|
||
adjusted_values.append(adjusted_value)
|
||
|
||
# 将第一个值追加到最后,闭合图形
|
||
adjusted_values.append(adjusted_values[0])
|
||
|
||
# 绘制雷达图
|
||
self.ax.plot(angle, adjusted_values, *args, **kw)
|
||
|
||
|
||
def generate_lab(max_values, length=5, step=1):
|
||
"""
|
||
根据最大值向量生成lab(标签)列表。
|
||
"""
|
||
lab = []
|
||
for max_val in max_values:
|
||
labels = [str(round(val, 2)) for val in np.arange(max_val - (length - 1) * step, max_val + step, step)]
|
||
lab.append(labels)
|
||
return lab
|
||
|
||
|
||
def generate_epo(max_values, length=6, step=1):
|
||
"""
|
||
根据最大值向量生成epo(刻度范围)列表。
|
||
"""
|
||
epo = []
|
||
for max_val in max_values:
|
||
range_values = [round(val, 2) for val in np.arange(max_val - (length - 1) * step, max_val + step, step)]
|
||
epo.append(range_values)
|
||
return epo
|
||
|
||
|
||
def plot_radar(data, max_values):
|
||
"""
|
||
绘制雷达图,根据数据和最大值生成图表。
|
||
"""
|
||
fig = plt.figure(figsize=(10, 8))
|
||
tit = data.columns.tolist()
|
||
lab = generate_lab(max_values, length=5, step=1)
|
||
epo = generate_epo(max_values, length=6, step=1)
|
||
|
||
plt.rcParams['font.sans-serif'] = ['SimHei']
|
||
radar = Radar(fig, tit, lab, epo)
|
||
|
||
# 遍历 DataFrame 的每一行
|
||
colors = plt.colormaps.get_cmap('tab20')
|
||
for i, (idx, row) in enumerate(data.iterrows()):
|
||
radar.plot(row.values.tolist(), '-', lw=2, color=colors(i), alpha=0.4, label=idx)
|
||
|
||
radar.ax.legend(bbox_to_anchor=(1.2, 1.05))
|
||
|
||
# plt.savefig('fig.png', dpi=300)
|
||
|
||
# 将图像保存到字节流中
|
||
img_bytes = BytesIO()
|
||
plt.savefig(img_bytes, format='png')
|
||
# 设置字节流的位置到开始
|
||
img_bytes.seek(0)
|
||
|
||
# plt.show()
|
||
plt.close()
|
||
return img_bytes
|
||
|
||
|
||
if __name__ == '__main__':
|
||
# 一个行名为样本名,列名为指标名的pd.dataframe
|
||
data = pd.read_csv('./radartest.csv', index_col=0)
|
||
|
||
# 任务设置的每个指标的最大值
|
||
max_values = [10, 15, 15, 10, 15, 5, 10, 10, 5, 5] # 示例最大值向量
|
||
# 使用这个函数
|
||
plot_radar(data, max_values)
|