一、雷达图
雷达图是一种显示多变量数据的图形方法。通常从同一中心点开始等角度间隔地射出三个以上的轴,每个轴代表一个定量变量,各轴上的点依次连接成线或几何图形。雷达图可以用来在变量间进行对比,或者查看变量中有没有异常值。另外,多幅雷达图之间或者雷达图的多层数据线之间,还可以进行总体数值情况的对比。轴的相对位置和角度通常是无信息的。每个变量都具有自己的轴,彼此间的距离相等,所有轴都有相同的刻度。在将数据映射到这些轴上时,需要注意预先对数值进行标准化处理,保证各个轴之间的数值比例能够做同级别的比较。
1、一个简单的示例:
# 导入必要的库
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
# 1、设置中文字体支持(解决中文显示问题)
plt.rcParams['font.sans-serif'] = ['SimHei'] # 使用黑体作为默认字体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示异常问题
# 2、创建测试数据(雷达图数据框架)
df = pd.DataFrame({
'group': ['A','B','C','D'], # 分组标签
'专业知识': [38, 1.5, 30, 4], # 各维度数据(后续同理)
'社交能力': [29, 10, 9, 34],
'领导能力': [15, 39, 23, 24],
'自我管理': [35, 31, 33, 14],
'学习能力': [32, 15, 32, 14]
})
# 3、雷达图参数设置
categories = list(df)[1:] # 提取维度名称(排除group列)
N = len(categories) # 维度数量(5个)
# 4、准备绘图数据(以第一组数据A为例)
values = df.loc[0].drop('group').values.flatten().tolist() # 提取A组数值
values += values[:1] # 闭合雷达图:将第一个值添加到列表末尾
# 5、计算每个维度的角度(极坐标转换)
angles = [n / float(N) * 2 * pi for n in range(N)] # 0到2π均匀分布的角度
angles += angles[:1] # 闭合角度序列
# 6、创建极坐标系子图
ax = plt.subplot(111, polar=True) # polar=True创建极坐标
# 7、设置维度标签(坐标轴刻度)
plt.xticks(angles[:-1], categories, color='grey', size=8) # 在每个角度位置设置刻度# 显示维度名称# 标签样式设置(颜色大小)
# 8、设置径向坐标(半径刻度)
ax.set_rlabel_position(0) # 将半径刻度标签角度设置为0度(正上方)
plt.yticks([10, 20, 30], ["10","20","30"], color="grey", size=7) # 设置径向刻度位置# 刻度标签# 标签样式设置(颜色大小)
plt.ylim(0, 40) # 设置径向坐标范围(0到40)
# 9、绘制雷达图轮廓
ax.plot(angles, values, color='#81AD70', linewidth=1, linestyle='solid')
# 10、填充雷达图区域
ax.fill(angles, values, color= '#A7C587', alpha=0.5)
# 显示图形
plt.show()
2、更多的示例:
# ----------- 库导入 -----------
import matplotlib.pyplot as plt
import pandas as pd
from math import pi
# ----------- 数据准备 -----------
df = pd.DataFrame({
'group': ['A','B','C','D'], # 组别标识
'var1': [38, 1.5, 30, 4], # 变量1数据
'var2': [29, 10, 9, 34], # 变量2数据
'var3': [8, 39, 23, 24], # 变量3数据
'var4': [7, 31, 33, 14], # 变量4数据
'var5': [28, 15, 32, 14] # 变量5数据
})
# ----------- 第一部分:定义单个蜘蛛图绘制函数 -----------
def make_spider(row, title, color):
""" 绘制单个蜘蛛图
参数:
row : 数据行索引
title : 图表标题
color : 颜色配置
"""
# 获取变量数量(排除group列)
categories = list(df.columns)[1:]
N = len(categories)
# 计算每个变量的角度(将圆周等分为N份)
angles = [n / float(N) * 2 * pi for n in range(N)]
angles += angles[:1] # 闭合曲线
# 初始化极坐标子图(2x2布局)
ax = plt.subplot(2, 2, row+1, polar=True)
# 极坐标轴调整:将第一个轴置于顶部,方向顺时针
ax.set_theta_offset(pi / 2) # 起始角度偏移90度
ax.set_theta_direction(-1) # 顺时针方向绘制
# 设置刻度标签:变量名称
plt.xticks(angles[:-1], categories, color='grey', size=8)
# 设置径向标签:数值刻度
ax.set_rlabel_position(0) # 刻度标签位置(角度)
plt.yticks([10, 20, 30], ["10","20","30"], color="grey", size=7)
plt.ylim(0, 40) # 固定刻度范围确保可比性
# 数据处理:获取当前行数据并闭合曲线
values = df.loc[row].drop('group').values.flatten().tolist()
values += values[:1] # 首尾相连形成闭合
# 绘制轮廓线及填充区域
ax.plot(angles, values, color=color, linewidth=2, linestyle='solid')
ax.fill(angles, values, color=color, alpha=0.4) # 半透明填充
# 添加带颜色标识的标题
plt.title(title, size=12, color=color, y=1.1) # y参数控制垂直位置
# ----------- 第二部分:生成全图 -----------
# 初始化画布(像素级尺寸控制)
my_dpi = 96
plt.figure(figsize=(1000/my_dpi, 1000/my_dpi), dpi=my_dpi)
# 创建颜色映射(使用Set2色板,按数据行数采样)
my_palette = plt.cm.get_cmap("Set2", len(df.index))
# 循环绘制每个数据组的蜘蛛图
for row in range(0, len(df.index)):
make_spider(
row=row,
title='组别 ' + df['group'][row], # 动态生成标题
color=my_palette(row) # 按索引分配颜色
)
# 显示图形
plt.show()
二、箱型图
箱形图是一种用作显示一组数据分布情况的统计图,因型状如箱子而得名。箱子的顶端和底端,分别代表上下四分位数。箱子中间的是中位数线,它将箱子一分为二。从箱子延伸出去的线条展现出了上下四分位数以外的数据,这代表离群值,也可称之为异常值。
箱形图最大的优势是,它以一种简单的方式,概括出一个或多个数值变量的分布,同时又不会占据太多空间。通过箱形图,我们可以很快知道一些关键的统计值,如中位数、上下四分位数等;也可以分析是否存在离群值、离群值分别是多少;整体来看,还可以检验数据是否对称、是否有偏向性,如果有,它偏向于哪一边;最后,我们还可以用多个箱型图,比较多组数据的分布,从而快速获得对数据结构、数据质量的认知。
1、简单的箱型图(需自己导入数据到df之后使用):
# 1、导入matplotlib的pyplot模块,通常别名为plt
import matplotlib.pyplot as plt
# 2、创建图形(figure)和坐标轴(axes)对象# figsize参数设置图形大小为8英寸宽×6英寸高(1英寸≈2.54厘米)
fig, ax = plt.subplots(figsize=(8,6))
# 3、在坐标轴上创建箱线图
# 使用DataFrame的'temp'列数据绘制箱线图 (默认显示:中位线、箱体范围、须线、离群点等统计特征)
boxplot = ax.boxplot(df['temp'])
# 4、设置坐标轴标签和标题
ax.set_xlabel('Column') # X轴标签(这里可以更具体,比如'Temperature')
ax.set_ylabel('Values') # Y轴标签(建议明确量纲,如'Temperature (°C)')
ax.set_title('Boxplot') # 图标题(可以更具体,如'Temperature Distribution')
# 5、显示图形窗口
plt.show()
2、以上箱型图更改颜色后:
# 1、导入matplotlib的pyplot模块
import matplotlib.pyplot as plt
# 2、创建画布和坐标轴(8英寸宽×6英寸高)
fig, ax = plt.subplots(figsize=(8,6))
# 3、创建箱线图并启用颜色填充(关键参数说明),patch_artist=True 允许自定义箱体颜色 # 其他默认参数:whis=1.5(须线范围),vert=True(垂直方向)
boxplot = ax.boxplot(df['temp'], patch_artist=True)
# 4、定义颜色配置方案
box_color = '#CCE198' # 箱体填充色
whisker_color = '#81AD70' # 须线颜色
cap_color = '#81AD70' # 须线端点颜色
flier_color = 'red' # 离群点颜色
median_color = '#81AD70' # 中位线颜色
# 5、设置箱线图各部件样式(进阶定制)
plt.setp(boxplot['boxes'], color=box_color) # 箱体边框颜色
plt.setp(boxplot['whiskers'], color=whisker_color) # 须线颜色
plt.setp(boxplot['caps'], color=cap_color) # 须线端点颜色
plt.setp(boxplot['fliers'], markerfacecolor=flier_color) # 离群点填充色
plt.setp(boxplot['medians'], color=median_color) # 中位线颜色
# 6、设置坐标轴和标题(建议更具体的标签)
ax.set_xlabel('Column')
ax.set_ylabel('Values')
ax.set_title('Boxplot')
# 7、显示图形
plt.show()
3、更多的示例(2):
# 导入必要的库
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon # 虽然导入但未使用,可以删除
# 固定随机种子保证结果可复现
np.random.seed(19680801)
# 1 # 第一部分:生成测试数据
# 生成模拟数据(包含正常值和离群值)
spread = np.random.rand(50) * 100 # 50个散布在0-100的值
center = np.ones(25) * 50 # 25个集中在50的值
flier_high = np.random.rand(10) * 100 + 100 # 10个高位离群值(100-200)
flier_low = np.random.rand(10) * -100 # 10个低位离群值(-100-0)
data = np.concatenate((spread, center, flier_high, flier_low)) # 合并成数据集
# 2 # 第二部分:创建2x3子图画布
fig, axs = plt.subplots(2, 3)
# 第一个子图:基础箱线图
axs[0, 0].boxplot(data)
axs[0, 0].set_title('basic plot')
# 第二个子图:带缺口的箱线图(notch=True)
axs[0, 1].boxplot(data, 1) # 第二个参数1表示notch=True
axs[0, 1].set_title('notched plot')
# 第三个子图:修改离群点符号(绿色菱形)
axs[0, 2].boxplot(data, 0, 'gD') # 'gD'表示绿色菱形标记
axs[0, 2].set_title('change outlier\npoint symbols')
# 第四个子图:不显示离群点
axs[1, 0].boxplot(data, 0, '') # 空字符串表示不显示
axs[1, 0].set_title("don't show\noutlier points")
# 第五个子图:水平箱线图
axs[1, 1].boxplot(data, 0, 'rs', 0) # 0表示vert=False(水平显示)
axs[1, 1].set_title('horizontal boxes')
# 第六个子图:修改须线长度(whis=0.75)
axs[1, 2].boxplot(data, 0, 'rs', 0, 0.75) # 最后0.75设置须线长度
axs[1, 2].set_title('change whisker length')
# 调整子图布局参数
fig.subplots_adjust(
left=0.08, right=0.98, # 左右边距
bottom=0.05, top=0.9, # 下上边距
hspace=0.4, wspace=0.3 # 子图水平和垂直间距
)
# 3 # 第三部分:多数据集箱线图
# 生成新的测试数据
spread = np.random.rand(50) * 100
center = np.ones(25) * 40 # 中心值改为40
flier_high = np.random.rand(10) * 100 + 100
flier_low = np.random.rand(10) * -100
d2 = np.concatenate((spread, center, flier_high, flier_low))
# 创建包含不同长度数据集的列表(注意最后一个元素是d2的每隔一个取一个值)
data = [data, d2, d2[::2]] # 使用列表处理不同长度的数据集
# 创建新图画多组箱线图
fig, ax = plt.subplots()
ax.boxplot(data) # 自动按不同数据集绘制多个箱线图
# 显示所有图形
plt.show()
4、更多的示例(2):
# 导入必要的库
import matplotlib.pyplot as plt
import numpy as np
# 定义要比较的分布名称列表
random_dists = ['Normal(1, 1)', 'Lognormal(1, 1)', 'Exp(1)', 'Gumbel(6, 4)', 'Triangular(2, 9, 11)']
N = 500 # 每个分布的样本数量
# 生成不同分布的随机数据
norm = np.random.normal(1, 1, N) # 正态分布
logn = np.random.lognormal(1, 1, N) # 对数正态分布
expo = np.random.exponential(1, N) # 指数分布
gumb = np.random.gumbel(6, 4, N) # 耿贝尔分布
tria = np.random.triangular(2, 9, 11, N) # 三角分布
# 生成用于自助法(Bootstrap)重采样的索引(所有分布使用相同的索引)
bootstrap_indices = np.random.randint(0, N, N)
# 创建包含原始数据和重采样数据的列表(交替排列)
data = [
norm, norm[bootstrap_indices], # 原始正态分布和重采样
logn, logn[bootstrap_indices], # 原始对数正态和重采样
expo, expo[bootstrap_indices], # 原始指数分布和重采样
gumb, gumb[bootstrap_indices], # 原始耿贝尔和重采样
tria, tria[bootstrap_indices], # 原始三角分布和重采样
]
# 创建画布和子图
fig, ax1 = plt.subplots(figsize=(10, 6))
fig.canvas.manager.set_window_title('A Boxplot Example') # 设置窗口标题
fig.subplots_adjust(left=0.075, right=0.95, top=0.9, bottom=0.25) # 调整边距
# 绘制箱线图(关键参数说明):
# notch=False 不显示缺口,sym='+' 离群点符号,vert=True 垂直显示,whis=1.5 须线范围
bp = ax1.boxplot(data, notch=False, sym='+', vert=True, whis=1.5)
# 设置箱线图样式
plt.setp(bp['boxes'], color='black') # 箱体边框颜色
plt.setp(bp['whiskers'], color='black') # 须线颜色
plt.setp(bp['fliers'], color='red', marker='+') # 离群点样式
# 添加浅灰色横向网格线
ax1.yaxis.grid(True, linestyle='-', which='major', color='lightgrey', alpha=0.5)
# 设置坐标轴和标题
ax1.set(
axisbelow=True, # 网格线在数据下方
title='Comparison of IID Bootstrap Resampling Across Five Distributions',
xlabel='Distribution',
ylabel='Value',
)
# 1 # 箱体颜色填充和中位数标记
box_colors = ['#81AD70', '#CCE198'] # 交替使用的两种颜色
num_boxes = len(data)
medians = np.empty(num_boxes) # 存储每个箱体的中位数值
for i in range(num_boxes):
# 获取每个箱体的坐标并填充颜色
box = bp['boxes'][i]
box_coords = np.column_stack([box.get_xdata(), box.get_ydata()])
ax1.add_patch(Polygon(box_coords, facecolor=box_colors[i % 2])) # 交替颜色
# 绘制中位线(覆盖在填充颜色上)
med = bp['medians'][i]
ax1.plot(med.get_xdata(), med.get_ydata(), 'k') # 黑色中位线
medians[i] = med.get_ydata()[0] # 记录中位数值
# 在箱体上方添加平均值星号标记(白色星星+黑色描边)
ax1.plot(np.average(med.get_xdata()), np.average(data[i]),
color='w', marker='*', markeredgecolor='k')
# 2 # 坐标轴调整
ax1.set_xlim(0.5, num_boxes + 0.5) # X轴范围
ax1.set_ylim(-5, 40) # Y轴范围
# 设置X轴标签(重复每个分布名称两次,对应原始和重采样)
ax1.set_xticklabels(np.repeat(random_dists, 2), rotation=45, fontsize=8)
# 3 # 在上方添加中位数数值标签
pos = np.arange(num_boxes) + 1 # 标签位置
upper_labels = [str(round(s, 2)) for s in medians] # 保留两位小数
for tick, label in zip(range(num_boxes), ax1.get_xticklabels()):
# 交替使用粗体和半粗体,颜色与箱体对应
k = tick % 2
ax1.text(pos[tick], 0.95, upper_labels[tick], # 0.95表示Y轴顶部附近
transform=ax1.get_xaxis_transform(), # 使用轴坐标系
horizontalalignment='center', size='x-small',
weight=weights[k], color=box_colors[k])
# 4 # 添加图例说明
# 原始数据说明(右下角)
fig.text(0.80, 0.08, f'{N} Random Numbers', backgroundcolor=box_colors[0],
color='black', weight='roman', size='x-small')
# 重采样数据说明
fig.text(0.80, 0.045, 'IID Bootstrap Resample', backgroundcolor=box_colors[1],
color='white', weight='roman', size='x-small')
# 平均值标记说明(使用星号)
fig.text(0.80, 0.015, '*', color='white', backgroundcolor='silver',
weight='roman', size='medium')
fig.text(0.815, 0.013, ' Average Value', color='black',
weight='roman', size='x-small')
plt.show()