如何为DataFrame每个索引循环生成雷达图?求问题分析
问题描述
我有一个结构如下的Pandas DataFrame:
import pandas as pd df = pd.DataFrame({"Name": ["A", "B", "C", "D", "E","F", "G"], "Tldiffto3": [2.0, -3.0, 2.0,17.0,7.0, 12.0,2.0], "LZdiffto3": [0.94, -5.0, 7.0,29.0,4.0, 10.0,2.5], "SZdiffto3": [0.94, -5.0, 7.0,29.0,4.0, 10.0,2.5], "KZdiffto3": [0.8, -9.0, 10.0,8.0,3.0, 11.0,4.5]})
已经实现了生成单个雷达图的代码:
import numpy as np import matplotlib.pyplot as plt # 变量类别 categories=list(df)[0:] N = len(categories) # 计算每个变量对应的角度 angles = [n / float(N) * 2 * np.pi for n in range(N)] angles += angles[:1] # 获取第一行数据并处理成闭合格式 values = df.loc[df.index[0]].values.flatten().tolist() values += values[:1] fig, ax = plt.subplots(figsize=(6, 6), subplot_kw=dict(polar=True), dpi = 100) # 绘制雷达图轮廓 ax.plot(angles, values, color='#1aaf6c', linewidth=1) # 填充区域 ax.fill(angles, values, color='#1aaf6c', alpha=0.25) # 调整坐标轴起始方向和顺序 ax.set_theta_offset(np.pi / 2) ax.set_theta_direction(-1) # 设置横轴标签 plt.xticks(angles[:-1], categories) # 调整横轴标签对齐方式 for label, angle in zip(ax.get_xticklabels(), angles): if angle in (0, np.pi): label.set_horizontalalignment('center') elif 0 < angle < np.pi: label.set_horizontalalignment('left') else: label.set_horizontalalignment('right') # 设置纵轴标签位置 ax.set_rlabel_position(180 / N) # 样式设置 ax.tick_params(colors='#222222') ax.tick_params(axis='y', labelsize=8) ax.grid(color='#AAAAAA') ax.spines['polar'].set_color('#222222') ax.set_facecolor('#FAFAFA')
现在想遍历DataFrame的索引,为每个Name对应的行生成独立的子图雷达图,尝试了以下循环代码但运行失败:
for i in range(df.index): ax.plot(angles, values, color='#1aaf6c', linewidth=1) ax.fill(angles, values, color='#1aaf6c', alpha=0.25)
错误原因分析
range(df.index)参数错误:df.index是索引对象,不是整数类型,range()需要传入整数参数,直接使用会触发类型错误。- 未更新循环内的数据:循环中始终使用第一行的
values数据,没有根据当前索引获取对应行的内容。 - 未创建独立子图:原代码仅生成了一个子图
ax,循环中直接在同一子图上叠加绘制,无法生成多个独立的雷达图。
解决方法
先规划子图布局,再遍历每行数据生成独立的雷达图子图,完整代码如下:
import pandas as pd import numpy as np import matplotlib.pyplot as plt df = pd.DataFrame({"Name": ["A", "B", "C", "D", "E","F", "G"], "Tldiffto3": [2.0, -3.0, 2.0,17.0,7.0, 12.0,2.0], "LZdiffto3": [0.94, -5.0, 7.0,29.0,4.0, 10.0,2.5], "SZdiffto3": [0.94, -5.0, 7.0,29.0,4.0, 10.0,2.5], "KZdiffto3": [0.8, -9.0, 10.0,8.0,3.0, 11.0,4.5]}) # 定义变量类别 categories = list(df.columns) N = len(categories) angles = [n / float(N) * 2 * np.pi for n in range(N)] angles += angles[:1] # 规划子图布局:3行3列,容纳7个图 rows = 3 cols = 3 fig, axes = plt.subplots(rows, cols, figsize=(15, 15), subplot_kw=dict(polar=True), dpi=100) # 扁平化子图数组,方便遍历 axes = axes.flatten() # 遍历每行数据 for idx, (i, row) in enumerate(df.iterrows()): ax = axes[idx] # 获取当前行数据并处理成闭合格式 values = row.values.flatten().tolist() values += values[:1] # 绘制雷达图 ax.plot(angles, values, color='#1aaf6c', linewidth=1) ax.fill(angles, values, color='#1aaf6c', alpha=0.25) # 设置子图标题为Name ax.set_title(row['Name'], y=1.1, fontsize=12) # 坐标轴和样式设置 ax.set_theta_offset(np.pi / 2) ax.set_theta_direction(-1) ax.set_xticks(angles[:-1]) ax.set_xticklabels(categories) # 调整横轴标签对齐方式 for label, angle in zip(ax.get_xticklabels(), angles): if angle in (0, np.pi): label.set_horizontalalignment('center') elif 0 < angle < np.pi: label.set_horizontalalignment('left') else: label.set_horizontalalignment('right') ax.set_rlabel_position(180 / N) ax.tick_params(colors='#222222') ax.tick_params(axis='y', labelsize=8) ax.grid(color='#AAAAAA') ax.spines['polar'].set_color('#222222') ax.set_facecolor('#FAFAFA') # 隐藏多余的空图 for j in range(idx+1, len(axes)): axes[j].axis('off') plt.tight_layout() plt.show()
代码说明
- 先创建3×3的子图网格,足够容纳7个雷达图,多余的子图最后隐藏。
- 使用
df.iterrows()遍历每行数据,同时获取索引和行内容,对应到子图位置。 - 每个子图独立处理数据、绘制雷达图并设置样式,确保图的独立性。
- 添加子图标题显示Name,方便区分不同的雷达图。
内容的提问来源于stack exchange,提问作者Hansson
相关产品推荐
相关产品推荐

