目录
1 三维散点图
# 导入必要的库
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.colors as mcolors
# 尝试读取Excel数据
data = pd.read_excel(r'E:\PythonProjects\experiments_figures\experiments_figures\三维散点图\data.xlsx',
engine='openpyxl',
sheet_name='Sheet1',
header=0)
# 定义投影颜色-映射
color = ['#00ced1', '#cc9900', '#b177de']
# 创建自定义颜色映射-颜色棒
hex_colors = ["#1e3cff", "#d631ff"]#蓝紫色
# 提取X、Y、Z坐标数据
xs = data.iloc[:, 0].values # 第一列作为X坐标
ys = data.iloc[:, 1].values # 第二列作为Y坐标
zs = data.iloc[:, 2].values # 第三列作为Z坐标
# 确保ns是数值类型
ns = pd.to_numeric(data.iloc[:, 3], errors='coerce').values # 第四列用于散点的大小
# 检查是否有转换失败的值(NaN),如果有则替换为0或其他合适的默认值
if np.isnan(ns).any():
print("警告:第四列中有非数值数据,已替换为默认值0")
ns = np.nan_to_num(ns, nan=0.0)
# 计算每个特征的最大最小值
x_min, x_max = np.min(xs), np.max(xs)
y_min, y_max = np.min(ys), np.max(ys)
z_min, z_max = np.min(zs), np.max(zs)
n_min, n_max = np.min(ns), np.max(ns) if np.min(ns) != np.max(ns) else (np.min(ns), np.min(ns) + 1)
# 计算每个坐标轴的偏移量
offset_x = (x_max + x_min) / 2
offset_y = (y_max + y_min) / 2
offset_z = (z_max + z_min) / 2
# 计算坐标轴范围
x_lower = x_min - offset_x
x_upper = x_max + offset_x
y_lower = y_min - offset_y
y_upper = y_max + offset_y
z_lower = z_min - offset_z
z_upper = z_max + offset_z
# 创建3D图形对象
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 创建自定义颜色映射
custom_cmap = mcolors.LinearSegmentedColormap.from_list("custom", hex_colors)
# 标准化z值以适应颜色映射
norm = mcolors.Normalize(vmin=z_min, vmax=z_max)
# 使用ns值计算球体大小 - 将ns值映射到合理的球体大小范围
if n_min == n_max:
sphere_sizes = np.full(len(ns), 0.05) # 如果所有值相同,使用默认大小
else:
# 将ns值标准化到0.02-0.1范围(球体半径)
sphere_sizes = 0.04 + ((ns - n_min) / (n_max - n_min)) * 0.14
# 定义球面网格
u = np.linspace(0, 2 * np.pi, 500)
v = np.linspace(0, np.pi, 500)
x_sphere = np.outer(np.cos(u), np.sin(v))
y_sphere = np.outer(np.sin(u), np.sin(v))
z_sphere = np.outer(np.ones(np.size(u)), np.cos(v))
# 为每个点绘制球体
for i in range(len(xs)):
# 获取当前点的颜色
color_val = custom_cmap(norm(zs[i]))
# 计算球体缩放
x_scale = sphere_sizes[i] * (x_max - x_min) / 2
y_scale = sphere_sizes[i] * (y_max - y_min) / 2
z_scale = sphere_sizes[i] * (z_max - z_min) / 2
# 绘制球体
ax.plot_surface(
xs[i] + x_scale * x_sphere,
ys[i] + y_scale * y_sphere,
zs[i] + z_scale * z_sphere,
color=color_val,
alpha=1,
shade=True,
zorder=10000
)
# 添加三个平面的投影
# XY平面投影 (z=0)
ax.scatter(xs, ys, np.full(len(xs), z_lower), c=color[0], marker='o', s=20, alpha=0.6, zorder=1)
# XZ平面投影 (y=0)
ax.scatter(xs, np.full(len(ys), y_lower), zs, c=color[1], marker='o', s=20, alpha=0.6, zorder=1)
# YZ平面投影 (x=0)
ax.scatter(np.full(len(zs), x_upper), ys, zs, c=color[2], marker='o', s=20, alpha=0.6, zorder=1)
# 设置刻度个数和标签字体大小
# X轴刻度设置
x_ticks = np.linspace(x_lower, x_upper, 6) # 设置6个X轴刻度
ax.set_xticks(x_ticks)
# Y轴刻度设置
y_ticks = np.linspace(y_lower, y_upper, 5) # 设置5个Y轴刻度
ax.set_yticks(y_ticks)
# Z轴刻度设置
z_ticks = np.linspace(z_lower, z_upper, 6) # 设置6个Z轴刻度
ax.set_zticks(z_ticks)
# 设置所有轴刻度标签的字体大小
ax.tick_params(axis='x', labelsize=12, pad=5) # X轴刻度标签字体大小
ax.tick_params(axis='y', labelsize=12, pad=7) # Y轴刻度标签字体大小
ax.tick_params(axis='z', labelsize=12, pad=7) # Z轴刻度标签字体大小
# 添加颜色条,关键修复:添加ax=ax参数
proxy = plt.cm.ScalarMappable(cmap=custom_cmap, norm=norm)
proxy.set_array(zs)
# 这里添加了ax=ax参数,指定颜色条关联的坐标轴
colbar = fig.colorbar(proxy, ax=ax, shrink=0.5, aspect=10, pad=0.15)
colbar.set_label('Z-value', fontsize=20) # 设置颜色条标签字体大小
colbar.ax.tick_params(labelsize=12) # 设置颜色条刻度标签字体大小
# 设置轴标签
ax.set_xlabel('X-axis', fontsize=20, labelpad=25)
ax.set_ylabel('Y-axis', fontsize=20, labelpad=25)
ax.set_zlabel('Z-axis', fontsize=20, labelpad=25)
# 设置标题
ax.set_title('3D scatter diagram', fontsize=24, pad=15)
# 设置坐标轴范围,确保投影点可见
ax.set_xlim(x_lower, x_upper)
ax.set_ylim(y_lower, y_upper)
ax.set_zlim(z_lower, z_upper)
# 调整视角以便更好地查看3D图
ax.view_init(elev=30, azim=135)
# 调整布局,确保所有元素都能正确显示
plt.tight_layout()
# 保存图片(可选)
plt.savefig('三维散点图.png', dpi=600, bbox_inches='tight')
plt.show()

2 三维瀑布图
# 导入必要的库
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# 从Excel文件读取数据
file_path = r'E:\PythonProjects\experiments_figures\experiments_figures\三维瀑布图\data.xlsx'
data = pd.read_excel(file_path, engine='openpyxl', sheet_name='Sheet1', header=0)
# 定义绘图顺序
drawing_order = ['Group1', 'Group2', 'Group3', 'Group4', 'Group5', 'Group6', 'Group7']
# 使用tab20颜色方案
tab20_colors = cm.tab20(np.linspace(0, 1, len(drawing_order)))
colors = {drawing_order[i]: tuple(tab20_colors[i]) for i in range(len(drawing_order))}
# 获取x值
x_values = data['Count'].values
# 创建图形和3D坐标轴,调整figsize以提供更多空间
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
# 减少子图边距,减小空白
plt.subplots_adjust(left=0.05, right=0.95, bottom=0.05, top=0.9)
# 创建图例补丁列表
legend_patches = []
# 为每个组绘制图形
for i, y_label in enumerate(reversed(drawing_order)):
color = colors[y_label]
z_values = data[y_label].values
x_valid = x_values
z_valid = z_values
# 为该组创建y位置
y_val = drawing_order.index(y_label)
y_points = np.full_like(x_valid, y_val)
# 绘制线条和点
ax.plot(x_valid, y_points, z_valid, color=color, alpha=1, linewidth=1.5)
ax.scatter(x_valid, y_points, z_valid, color=color, marker='o', s=20)
# 为奇数编号的点添加标签,增大标签字体
for x, y, z in zip(x_valid, y_points, z_valid):
if int(x) % 2 == 1:
label = f'{z:.1f}' if isinstance(z, float) else str(z)
ax.text(x, y, z + 0.5, label, ha='center', va='bottom', fontsize=12)
# 创建3D多边形以实现瀑布效果
verts = [list(zip(x_valid, y_points, z_valid)),
list(zip(x_valid, y_points, np.zeros_like(z_valid)))]
poly = Poly3DCollection([verts[0] + verts[1][::-1]], alpha=0.25)
poly.set_color(color)
ax.add_collection3d(poly)
# 添加到图例
legend_patches.append(plt.Line2D([0], [0], color=color, lw=2, label=y_label))
# 添加图例,调整位置和字体大小
ax.legend(handles=legend_patches,
loc='upper left',
fontsize=12,
frameon=True,
shadow=False,
fancybox=True,
framealpha=0.8,
bbox_to_anchor=(1.05, 1))
# 设置标签和标题,增大字体
ax.set_xlabel('Count', fontsize=14, labelpad=10)
ax.set_ylabel('Groups', fontsize=14, labelpad=10)
ax.set_zlabel('Values', fontsize=14, labelpad=10)
ax.set_title('3D Waterfall Chart of Groups', fontdict={'size': 18})
# 设置y轴刻度标签字体大小
ax.set_yticks(range(len(drawing_order)))
ax.set_yticklabels(drawing_order, fontsize=12)
# 调整图表限制以确保所有数据可见
margin = 0.1
x_min, x_max = min(x_values), max(x_values)
y_min, y_max = 0, len(drawing_order) - 1
z_min, z_max = 0, data[drawing_order].values.max() * 1.15
ax.set_xlim(x_min - margin, x_max + margin)
ax.set_ylim(y_min - margin, y_max + margin)
ax.set_zlim(z_min, z_max)
# 优化视角
ax.view_init(elev=35, azim=-45)
# 保存图片为600 DPI的PNG格式
plt.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\三维瀑布图\三维瀑布图.png',
dpi=600,
bbox_inches='tight',
pad_inches=0.2)
# 显示图表
plt.tight_layout()
plt.show()

3 三维热图
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
# 设置中文字体支持(解决中文显示问题)
plt.rcParams["font.family"] = ["SimHei"] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
# ================== 数据准备阶段 ==================
# 读取Excel数据 - 使用index_col=0来将第一列设置为索引
data = pd.read_excel(r'E:\PythonProjects\experiments_figures\experiments_figures\三维热图\data.xlsx',
engine='openpyxl',
sheet_name='Sheet1',
index_col=0) # 这里设置第一列为索引,也就是A到J这些字母
# ================== 数据归一化 ==================
# 提取所有值用于归一化
all_values = data.values.flatten()
# 找出最大值和最小值
min_val = np.min(all_values)
max_val = np.max(all_values)
# 执行Min-Max归一化 (将数据缩放到0-1范围)
normalized_data = (data - min_val) / (max_val - min_val)
# ================== 创建自定义颜色映射 ==================
##1.第一种使用颜色库
# cmap = plt.cm.coolwarm
## 2.定义自定义颜色映射,使用16进制颜色代码
# 从低值到高值的颜色渐变
custom_colors = ["#8e0152", "#c51b7d", "#f1b6da", # 紫色系
"#f7f7f7", # 中性白
"#e6f5d0", "#b8e186", "#4d9221"] # 绿色系
# custom_colors = [
# "#e5f5f9", # 浅蓝
# "#99d8c9", # 蓝绿过渡
# "#66c2a4", # 中绿
# "#238b45", # 深绿
# "#00441b" # 墨绿
# ]
# custom_colors = ["#FFF5EB", # 极浅橙 (接近白)
# "#FEE6CE", # 浅奶油橙
# "#FDD0A2", # 淡橙
# "#FDAE6B", # 柔橙
# "#FD8D3C", # 标准浅橙
# "#F16913", # 明亮橙
# "#D94801", # 饱和橙
# ]
# custom_colors = [
# "#0ebeff",
# "#3ea5f0",
# "#6e8ce1",
# "#9f74d1",
# "#cf5bc2",
# "#ff42b3",
# ]
# custom_colors = [
# "#FFC0CB",
# "#F3B3C6",
# "#E699B3",
# "#CC6699",
# "#B36666",
# "#993366",
# ]
#### 创建自定义颜色映射
cmap = LinearSegmentedColormap.from_list('custom_colormap', custom_colors)
# ================== 绘制3D热图 ==================
# 创建一个3D图形
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')
# 获取数据维度
rows, cols = data.shape
# 创建x, y坐标网格 - 使用中心坐标
x, y = np.meshgrid(np.arange(cols), np.arange(rows))
# 展平x, y网格和数据矩阵以便绘图
x = x.flatten()
y = y.flatten()
z = np.zeros_like(x) # 起始高度为0
# 获取归一化后的值作为柱子高度
dz = normalized_data.values.flatten()
# 使用原始数据值的归一化来设置颜色
norm = plt.Normalize(min_val, max_val)
colors = cmap(norm(data.values.flatten()))
# 绘制3D柱状图 - 设置dx和dy相等以确保俯视图为正方形
bar_width = 0.6 # 将宽度设置得更大一些,接近1
ax.bar3d(x, y, z, bar_width, bar_width, dz, shade=True, color=colors, alpha=1)
# 设置x轴和y轴的显示范围,确保正方形布局
ax.set_box_aspect([cols, rows, max(0.7*max(cols, rows), np.max(dz)*1.2)]) # 调整z轴高度比例
# 设置坐标轴标签
ax.set_xlabel('特征', labelpad=10, fontsize=18)
ax.set_ylabel('分组', labelpad=10, fontsize=18)
ax.set_zlabel('归一化数值 (0-1)', labelpad=10, fontsize=18)
# 设置x轴刻度标签为列名,并使其居中对应每个柱子
ax.set_xticks(np.arange(cols) + bar_width/2)
ax.set_xticklabels(data.columns, rotation=45, ha='right', fontsize=18)
# 设置y轴刻度标签为行名,并使其居中对应每个柱子
ax.set_yticks(np.arange(rows) + bar_width/2)
ax.set_yticklabels(data.index, fontsize=18)
# 设置z轴的刻度 - 调整为5个刻度点
z_ticks = np.linspace(0, 1.5, 5)
ax.set_zticks(z_ticks)
ax.set_zticklabels([f"{val:.2f}" for val in z_ticks], fontsize=18)
# 调整视角以便更好地查看3D图
ax.view_init(elev=30, azim=225)
# 添加颜色条以显示原始数值对应的颜色
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
sm.set_array([])
cbar = plt.colorbar(sm, ax=ax, pad=0.1, shrink=0.7, aspect=20)
cbar.set_label('原始数值范围', fontsize=18)
cbar.ax.tick_params(labelsize=18) # 颜色棒刻度字体大小
# 添加说明
plt.title('三维归一化热图', fontsize=16, pad=20)
# 确保从俯视图看是正方形的
ax.set_proj_type('ortho') # 使用正交投影
# 调整布局
plt.tight_layout()
# 保存图片(可选)
plt.savefig('三维热图.png', dpi=600, bbox_inches='tight')
plt.show()

4 云雨图
# 导入必要的库
import numpy as np # 数值计算库
import pandas as pd # 数据处理库
import matplotlib.pyplot as plt # 绘图库
# ==================== 1. 数据准备 ====================
# 定义Excel文件路径(注意:r表示原始字符串,避免转义字符问题)
file_path = r'E:\PythonProjects\experiments_figures\experiments_figures\云雨图\data.xlsx'
# 使用pandas读取Excel文件
# engine='openpyxl':指定使用openpyxl引擎读取xlsx文件
# sheet_name='Sheet1':读取第一个工作表
# header=0:使用第一行作为列名
df = pd.read_excel(file_path, engine='openpyxl', sheet_name='Sheet1', header=0)
# 数据集的特征变量(列名)
categories = ['A', 'B', 'C', 'D', 'E']
# ==================== 2. 可视化设置 ====================
# 创建图形和坐标轴,设置图形大小为10x8英寸
fig, ax = plt.subplots(figsize=(10, 8))
# 定义颜色方案(颜色个数与变量个数相同)
# 小提琴图颜色(半透明填充) 箱线图颜色(实色填充)
box_colors = violin_colors = ["#d36a87", "#ea9979", "#83b6b5", "#bcdfa7", "#a596ee"]
# box_colors = violin_colors = ['#9bb55e', '#fcd744', '#dc8e4e', '#ba7ab1', '#ea617b']
# 设置类别在x轴上的位置(0,1,2,3,4)
positions = np.arange(len(categories))
box_width = 0.15 # 箱形图宽度
violin_width = 0.5 # 小提琴图宽度
# ==================== 3. 绘制图形 ====================
# 遍历每个类别进行绘图
for i, category in enumerate(categories):
# 获取当前类别的数据值
data_points = df[category].values
# ----------------- 3.1 绘制箱形图 -----------------
# 箱形图位置向左微调(避免与小提琴图完全重叠)
box_pos = positions[i] - box_width / 100
# 绘制箱形图(boxplot)
box = ax.boxplot(
data_points,
positions=[box_pos], # 指定位置
widths=box_width, # 设置宽度
patch_artist=True, # 允许填充颜色
showfliers=False, # 不单独显示离群点(因为后面会用散点图显示)
notch=True, # 显示中位数置信区间缺口
# 中位数线属性设置
medianprops={'color': 'black', 'linewidth': 3},
# 箱体属性设置
boxprops={'facecolor': box_colors[i], 'edgecolor': violin_colors[i], 'linewidth': 3},
# 须线属性设置
whiskerprops={'color': violin_colors[i], 'linewidth': 3},
# 端点线属性设置
capprops={'color': violin_colors[i], 'linewidth': 3}
)
# ----------------- 3.2 绘制半小提琴图 -----------------
# 小提琴图位置向右微调(与箱线图对称)
violin_pos = positions[i] + box_width / 50
# 绘制完整小提琴图(violinplot)
violin = ax.violinplot(
data_points,
positions=[violin_pos], # 指定位置
widths=violin_width, # 设置宽度
showmeans=False, # 不显示均值
showmedians=False, # 不显示中位数(箱线图已显示)
showextrema=False # 不显示极值
)
# 修改小提琴图只显示右侧一半
for pc in violin['bodies']:
# 设置小提琴图颜色和透明度
pc.set_facecolor(violin_colors[i])
pc.set_edgecolor(violin_colors[i])
pc.set_alpha(0.35) # 设置透明度
# 获取路径顶点
vertices = pc.get_paths()[0].vertices
# 只保留x坐标大于中心位置的部分(实现半小提琴图效果)
vertices[:, 0] = np.where(
vertices[:, 0] > violin_pos,
vertices[:, 0],
violin_pos
)
# ----------------- 3.3 添加数据点 -----------------
# 在箱形图位置添加抖动点(jitter scatter plot)
ax.scatter(
# x坐标:在箱线图位置附近添加随机抖动(避免点重叠)
np.random.normal(positions[i] - box_width, 0.04, len(data_points)),
# y坐标:实际数据值
data_points,
color=violin_colors[i], # 颜色与小提琴图一致
alpha=0.8, # 透明度
s=50, # 点大小
edgecolor='white', # 边缘颜色
linewidth=0.8, # 边缘线宽
zorder=3 # 图层顺序(确保点在最上层)
)
# ==================== 4. 图表美化 ====================
# 设置x轴刻度位置和标签
ax.set_xticks(positions)
ax.set_xticklabels(categories, fontsize=20)
# 设置y轴标签和刻度标签字体大小(修复警告的部分)
ax.set_ylabel('Density', fontsize=20)
# 直接设置刻度标签的字体大小,而不是重新设置标签
plt.yticks(fontsize=20)
# 添加y轴网格线(虚线,半透明)
ax.grid(axis='y', linestyle='--', alpha=0.7)
# 显示边框
for spine in ['top', 'right', 'bottom', 'left']:
ax.spines[spine].set_visible(True)
ax.spines[spine].set_linewidth(2) # 设置边框线宽
ax.spines[spine].set_color('black') # 设置边框颜色
# 添加图表标题(pad参数控制标题与图的间距)
plt.title('Raincloud plots', pad=20, fontsize=22)
# 调整子图布局(避免元素被裁剪)
plt.tight_layout()
# 保存图片为600 DPI的PNG格式
plt.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\云雨图\云雨图.png',
dpi=600,
bbox_inches='tight',
pad_inches=0.2)
# 显示图表
plt.tight_layout()
plt.show()

5 单类别散点矩阵图
# 导入必要的库
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import pearsonr
from matplotlib.colors import to_rgba
# Load data
file_path = r'E:\PythonProjects\experiments_figures\experiments_figures\单类别散点矩阵图\data.xlsx'
df = pd.read_excel(file_path, engine='openpyxl', sheet_name='Sheet1', header=0)
columns = variables = labels = ['A', 'B', 'C', 'D', 'E']
# color_list = ['#E7B800', '#91a721', '#02AFBB'] # 设置颜色
# color_list = ['#FCE38A', '#F38181', '#95E1D3']
color_list = ['#00AFBB', '#E7B800', '#FC4E07']
# color_list = ['#F84914', '#59187E', '#2FB4AF']
# color_list = ['#FA6494', '#C97BEF', '#80D3BA']
# color_list = ['#F8766D', '#7CAE00', '#00BFC4']
# color_list = ['#CC4678FF', '#0D0887FF', '#F0F921FF']
col = len(columns) # 变量个数
# P值的影响
def calculate_p(p_value):
if p_value < 0.001:
return '***'
elif p_value < 0.01:
return '**'
elif p_value < 0.05:
return '*'
else:
return ''
# 创建画布
fig, axes = plt.subplots(col + 1, col + 1, figsize=((col + 1) * 3, (col + 1) * 3))
fig.subplots_adjust(hspace=0.1, wspace=0.1)
# 设置图形格式
for i, row_var in enumerate(columns):
for j, col_var in enumerate(columns):
ax = axes[i, j]
# KDE 绘制
if i == j:
sns.kdeplot(data=df, x=col_var, ax=ax, alpha=0.6,
fill=True, color=color_list[0], linewidth=0)
if ax.get_legend():
ax.get_legend().remove()
# 下三角:带回归线的散点图
elif i > j:
sns.scatterplot(data=df, x=col_var, y=row_var,
color=color_list[1], ax=ax, s=40, edgecolor='none', alpha=0.8)
sns.regplot(data=df, x=col_var, y=row_var, ax=ax,
color=color_list[1], scatter=False, truncate=False)
if ax.get_legend():
ax.get_legend().remove()
# 上三角:相关信息
elif j > i:
ax.set_facecolor(to_rgba(color_list[2], alpha=0.2))
ax.set_xticks([])
ax.set_yticks([])
overall_corr, overall_p = pearsonr(df[row_var], df[col_var])
stars = calculate_p(overall_p)
ax.text(0.5, 0.5, f"Cor : {overall_corr:.3f}\n{stars}", ha='center',
va='center', fontsize=16, family='Times New Roman', fontweight='bold')
# 增加第6列(箱形图+半个小提琴图)和第6行(直方图)
for i, row_var in enumerate(columns):
if i < col:
# 第六栏云雨图
ax = axes[i, col]
subset_data = df[row_var]
center_pos = 0
box_width = 0.15 # 箱子宽度
violin_width = 0.6 # 小提琴宽度
# 添加抖动的点
jitter = np.random.normal(loc=center_pos - box_width, scale=0.04, size=len(subset_data))
ax.scatter(jitter, subset_data, s=20,
facecolor=color_list[2], edgecolor='black',
linewidth=0.5, alpha=0.8, zorder=3)
# 箱图
ax.boxplot(subset_data, positions=[center_pos], manage_ticks=False,
patch_artist=True, widths=box_width,
medianprops={'color': 'white', 'linewidth': 2},
boxprops={'facecolor': color_list[2], 'alpha': 0.7},
whiskerprops={'color': color_list[2], 'linewidth': 2},
capprops={'color': color_list[2], 'linewidth': 2},
showfliers=False, zorder=2)
# 小提琴图
violin = ax.violinplot(
subset_data,
positions=[center_pos],
widths=violin_width,
showmeans=False,
showmedians=False,
showextrema=False,
)
# 修改小提琴情节,只显示右半部分
for pc in violin['bodies']:
pc.set_facecolor(color_list[2])
pc.set_edgecolor(color_list[2])
pc.set_alpha(0.3)
vertices = pc.get_paths()[0].vertices
vertices[:, 0] = np.where(vertices[:, 0] > center_pos, vertices[:, 0], center_pos)
ax.set_xticks([])
ax.set_xlim(-0.6, 0.6)
if i < col: # 检查避免越界
# 第6行(直方图)
ax = axes[col, i]
sns.histplot(data=df, x=row_var, bins=15, shrink=0.8, color=color_list[1], ax=ax, alpha=0.9)
if ax.get_legend():
ax.get_legend().remove()
# 在位置[ 5、5 ] (第6行,第6列)处添加组合雨云图
ax = axes[col, col]
ax.clear()
# 为雨云图设置变量和位置
# variables = ['A', 'B', 'C', 'D', 'E']
positions = np.arange(len(variables))
data_columns = columns[:5] if len(columns) >= 5 else columns
# 对每个变量进行绘图
for i, (var_name, col_name) in enumerate(zip(variables, data_columns)):
if col_name in df.columns:
data = df[col_name].dropna().values
# 对于这个变量的定位
pos = positions[i]
# 1. 添加箱线图
box_parts = ax.boxplot([data], positions=[pos], widths=0.2, patch_artist=True,
showfliers=False, medianprops={'color': 'white', 'linewidth': 1.5})
for box in box_parts['boxes']:
# box.set(facecolor=color_list[i % len(color_list)], alpha=0.7)
box.set(facecolor=color_list[0], alpha=0.7)
# 2. 添加抖动点
jitter = np.random.normal(loc=pos, scale=0.08, size=len(data))
ax.scatter(jitter, data, s=15, alpha=0.7,
# color=color_list[i % len(color_list)],
color=color_list[0],
edgecolor='black', linewidth=0.4)
# 设置标签和样式
ax.set_xticks(positions)
ax.set_xticklabels(variables, fontsize=14, family='Times New Roman')
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
for i in range(col + 1):
for j in range(col + 1):
ax = axes[i, j]
ax.set_xlabel('')
ax.set_ylabel('')
# 添加标题
if i == 0 and j < col:
ax.set_title(columns[j], fontsize=16, pad=15)
if j == 0 and i < col:
ax.set_ylabel(columns[i], fontsize=16, labelpad=15)
ax.spines['top'].set_visible(False)
ax.spines['right'].set_visible(False)
if i < j and j < col:
ax.spines['left'].set_visible(False)
ax.spines['bottom'].set_visible(False)
# labels = ['A', 'B', 'C', 'D', 'E']
# 为第六列(索引5)的行1-5(索引0-4)添加x轴标签
for i in range(min(5, col)): # 确保不超过列数
ax = axes[i, col] # 获取第i行第6列的坐标轴
ax.set_xticks([0]) # 在位置0设置刻度
ax.set_xticklabels([labels[i]], fontsize=14, family='Times New Roman') # 设置标签
ax.set_xlim(-0.6, 0.6) # 调整x轴范围确保标签可见
# 为第六行(索引5)的列1-5(索引0-4)添加x轴标签
for j in range(min(5, col)): # 确保不超过列数
ax = axes[col, j] # 获取第6行第j列的坐标轴
ax.set_xticks([]) # 清除现有刻度
ax.set_xticks([df[columns[j]].mean()]) # 在均值位置设置刻度
ax.set_xticklabels([labels[j]], fontsize=14, family='Times New Roman')
# 保存图片为600 DPI的PNG格式
plt.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\单类别散点矩阵图\单类别散点矩阵图.png',
dpi=600,
bbox_inches='tight',
pad_inches=0.2)
# 显示图表
plt.tight_layout()
plt.show()

6 环形热图
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import pandas as pd
import circlify
from matplotlib.patches import Rectangle
import warnings
# 过滤tight_layout与极坐标图不兼容的警告
warnings.filterwarnings("ignore", message="This figure includes Axes that are not compatible with tight_layout")
# --------- 生成示例数据 ---------
try:
# 尝试读取Excel数据
df = pd.read_excel('data.xlsx', engine='openpyxl',
sheet_name='Sheet1', header=0, index_col=0)
except Exception as e:
print(f"读取文件出错: {e}")
print("使用随机生成的数据进行演示")
np.random.seed(40)
pathways = [f"Pathway_{i + 1}" for i in range(50)]
samples = ['A', 'B', 'C']
data = np.round(np.random.uniform(-1, 1, (len(pathways), len(samples))), 3)
df = pd.DataFrame(data, index=pathways, columns=samples)
# 颜色配置
color = ["#81D4FA", "white", "#EC407A"]
# --------- 环形热图绘制 ---------
def circular_heatmap(df, gap_after=20, color_map=None, figsize=(10, 10), save_path='环形热图.png'):
n_rows, n_cols = df.shape
theta_gap = np.deg2rad(gap_after)
cell_width = (2 * np.pi - theta_gap) / n_rows
if color_map is None:
color_map = mcolors.LinearSegmentedColormap.from_list(
'custom', color)
norm = mcolors.Normalize(vmin=-1, vmax=1)
fig, ax = plt.subplots(figsize=figsize, subplot_kw={'polar': True})
# 计算最外层热图的半径
max_radius = 1 + (n_cols - 1) * 0.2 + 0.18
# 标签半径设置为热图外围
label_radius = max_radius + 0.2
# 绘制每个样本组的圆环层
for col_idx, col in enumerate(df.columns):
radius = 1 + col_idx * 0.2
for row_idx, (row_name, row) in enumerate(df.iterrows()):
theta_start = row_idx * cell_width
theta_end = theta_start + cell_width
val = row[col]
ax.bar(
(theta_start + theta_end) / 2, 0.18, width=cell_width * 0.9,
bottom=radius, color=color_map(norm(val)),
edgecolor='white', linewidth=1, align='center'
)
# 添加路径名(列名)- 放置在热图外围
for row_idx, row_name in enumerate(df.index):
theta = row_idx * cell_width + cell_width / 2
text_angle = np.rad2deg(theta)
# 根据角度调整文本的对齐方式和旋转
if 0 <= text_angle < 90:
ha, va = 'left', 'bottom'
rotation = text_angle
elif 90 <= text_angle < 180:
ha, va = 'right', 'bottom'
rotation = text_angle
elif 180 <= text_angle < 270:
ha, va = 'right', 'top'
rotation = text_angle - 180
else: # 270 <= text_angle <= 360
ha, va = 'left', 'top'
rotation = text_angle - 180
ax.text(theta, label_radius, row_name,
ha=ha, va=va,
rotation=rotation,
fontsize=10, color='black')
# 添加样本名(行名)
for col_idx, col in enumerate(df.columns):
ax.text(-theta_gap / 2, 1 + col_idx * 0.2 + 0.09, col,
ha='left', va='center', fontsize=12, color='black', rotation=90)
# 图例 - 调整colorbar位置和大小
sm = plt.cm.ScalarMappable(cmap=color_map, norm=norm)
sm.set_array([])
# 创建一个新的axes来放置colorbar
cbar_ax = fig.add_axes([0.48, 0.32, 0.03, 0.3])
# 创建colorbar
cbar = fig.colorbar(sm, cax=cbar_ax)
cbar.set_label('Value', fontsize=18)
cbar.ax.tick_params(labelsize=16)
# 设置轴的限制
ax.set_rlim(0, label_radius + 0.5)
# 其它美化
ax.set_axis_off()
plt.suptitle('Circular Heatmap', fontsize=20, y=0.97)
# 保存图片 - 现在有默认路径,会自动保存
plt.savefig(save_path, dpi=600, bbox_inches='tight', pad_inches=0.2)
print(f"图片已保存至: {save_path}")
# 显示图表
plt.show()
return fig, ax
# 调用函数生成环形热图 - 不指定路径将使用默认的'relative_path_heatmap.png'
circular_heatmap(df)
# 如果需要自定义保存路径,可以这样调用:
# circular_heatmap(df, save_path='自定义名称.png')

7 直方热图
# 导入必要的库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置中文字体支持(解决中文显示问题)
plt.rcParams["font.family"] = ["SimHei"] # 使用黑体
plt.rcParams['axes.unicode_minus'] = False # 解决负号显示为方块的问题
# ================== 数据准备阶段 ==================
# 读取Excel数据 - 使用index_col=0来将第一列设置为索引
data = pd.read_excel(r'E:\PythonProjects\experiments_figures\experiments_figures\直方热图\data.xlsx',
engine='openpyxl',
sheet_name='Sheet1',
index_col=0) # 这里设置第一列为索引,也就是A到J这些字母
# 计算每个特征的统计量(这里使用F1列作为示例)
feature_stats = data.mean(axis=1)
color = 'PiYG'
# color = 'coolwarm'
# color = 'YlGn'
# color = 'RdYlGn'
# color = 'PuOr'
# ================== 创建复合图形 ==================
# 设置每个正方形单元格的大小(以英寸为单位)
cell_size_inches = 0.5 # 可以调整这个值来改变正方形大小
# 计算图形的总大小,基于数据尺寸和期望的单元格大小
rows, cols = data.shape
fig_width = (cell_size_inches * cols) * 2 # 增加50%的宽度用于直方图
fig_height = cell_size_inches * rows + 1 # 加额外空间给标题和标签
# 创建图形
fig = plt.figure(figsize=(fig_width, fig_height))
# 创建热图的轴 - 左侧
ax_heatmap = fig.add_axes([0.1, 0.15, 0.6, 0.7]) # [left, bottom, width, height]
# 创建横向条形图的轴 - 右侧
ax_bar = fig.add_axes([0.63, 0.15, 0.2, 0.7]) # 与热图相同的高度和垂直位置
# 创建颜色棒的轴
cbar_ax = fig.add_axes([0.85, 0.32, 0.03, 0.3]) # 颜色棒位置
# ================== 绘制热图 ==================
heatmap = sns.heatmap(data,
ax=ax_heatmap,
annot=True, # 显示数值
cmap=color, # 使用选定的颜色映射
fmt='.1f', # 数值格式化为一位小数
linewidths=0.5, # 网格线宽度
square=True, # 确保单元格为正方形
cbar_ax=cbar_ax, # 使用指定的颜色棒轴
cbar_kws={
'label': 'Value', # 颜色棒标签
'orientation': 'vertical', # 颜色棒方向
})
ax_heatmap.set_title('Heatmap', fontsize=14)
ax_heatmap.set_xlabel('Group', fontsize=12)
ax_heatmap.set_ylabel('Classification', fontsize=12)
# ================== 绘制横向条形图 ==================
# 获取热图的颜色映射 - 使用新的方法替代get_cmap
cmap = plt.colormaps[color]
# 归一化特征值到[0,1]范围,用于颜色映射
norm = plt.Normalize(vmin=data.values.min(), vmax=data.values.max())
# 创建横向条形图,使用热图的颜色映射
bars = ax_bar.barh(y=feature_stats.index,
width=feature_stats.values,
height=0.8,
color=[cmap(norm(value)) for value in feature_stats.values])
# 反转y轴,使顺序与热图一致
ax_bar.invert_yaxis()
# 为每个条形添加标签,显示具体数值
for i, v in enumerate(feature_stats.values):
offset = max(feature_stats.values) * 0.45 # 使用最大值的45%作为偏移
ax_bar.text(v - offset, i, f'{v:.1f}', va='center', fontsize=10,
color='black' if norm(v) > 0.4 else 'white') # 根据背景色调整文字颜色
# 添加标题和标签
ax_bar.set_xlabel('Mean Value', fontsize=12)
ax_bar.set_ylabel('') # 隐藏y轴标签,因为热图已经有标签
# 设置横轴刻度个数
x_min = 0
x_max = max(feature_stats.values) * 1.2 # 留出20%的空白
num_ticks = 3 # 设置想要的刻度数量
x_ticks = np.linspace(x_min, x_max, num_ticks)
ax_bar.set_xticks(x_ticks)
ax_bar.set_xticklabels([f'{x:.1f}' for x in x_ticks]) # 格式化刻度标签
# 获取热图的y轴范围
heatmap_y_min, heatmap_y_max = ax_heatmap.get_ylim()
# 设置条形图的y轴范围与热图一致
ax_bar.set_ylim(heatmap_y_min-0.5, heatmap_y_max-0.5)
# 隐藏条形图的y轴标签,避免重复
ax_bar.set_yticklabels([])
# 保存图片为600 DPI的PNG格式
# 移除tight_layout,因为手动创建的轴不兼容
plt.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\直方热图\直方热图.png',
dpi=600,
bbox_inches='tight',
pad_inches=0.2)
# 显示图表
plt.show()

8 相关性热图
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from matplotlib.patches import Wedge
from matplotlib.colors import LinearSegmentedColormap
def correlation_pie_plot(corr_matrix, figsize=(8, 6), radius=1.0):
"""
创建相关性矩阵可视化图
上三角显示数值,下三角显示饼图状圆形,对角线显示完全相关(值为1)的彩色圆形
参数:
-----------
corr_matrix : pandas DataFrame
相关性矩阵
radius : float
圆形的半径(默认: 1.0)
"""
# 获取变量数量
n_vars = len(corr_matrix.columns)
# 创建图形和坐标轴
fig, ax = plt.subplots(figsize=figsize)
# 设置颜色映射 - 使用Viridis颜色方案
# Viridis是从深紫色(#440154)到亮黄色(#fde725)的渐变色系
colors = ["#81D4FA", "white", "#EC407A"]
# colors = ["#440154", "#482878", "#3e4989", "#31688e", "#26828e",
# "#1f9e89", "#35b779", "#6ece58", "#b5de2b", "#fde725"]
# colors = ["#8e0152", "#c51b7d", "#f1b6da","#f7f7f7", # 中性白
# "#e6f5d0", "#b8e186", "#4d9221"] # 绿色系
# colors = ["#9e0142", "#d53e4f", "#f46d43", "#fdae61", "#fee08b",
# "#ffffbf", "#e6f598", "#abdda4", "#66c2a5", "#3288bd", "#5e4fa2"]
# 创建线性分段颜色映射,将颜色列表转换为颜色映射对象
cmap = LinearSegmentedColormap.from_list("custom_diverging", colors)
# 绘制相关性矩阵
for i in range(n_vars):
for j in range(n_vars):
# 获取当前位置的皮尔逊相关系数值
corr_val = corr_matrix.iloc[i, j]
# 上三角区域 - 显示数值文本
if i < j:
# 根据相关系数正负选择文本颜色:正相关用深色,负相关用亮色
text_color = colors[-1] if corr_val > 0 else colors[0]
ax.text(i, j, f"{corr_val:.2f}", ha='center', va='center',
color=text_color, fontsize=12, fontweight='bold')
# 对角线区域 - 显示完全相关(值为1)的彩色圆形
elif i == j:
# 绘制填充圆形,颜色表示完全相关(值为1)
# cmap(1.0)获取颜色映射中最大值对应的颜色(亮黄色)
circle = plt.Circle((i, j), radius,
color=cmap(1.0))
ax.add_artist(circle)
# 在圆形中心添加黑色文本"1.00"
ax.text(i, j, "1.00", ha='center', va='center',
color='black', fontsize=12, fontweight='bold')
# 下三角区域 - 显示饼图状相关性圆形
elif i > j:
# 绘制空心的灰色边框圆形
circle = plt.Circle((i, j), radius, fill=False, edgecolor='gray')
ax.add_artist(circle)
# 添加楔形(饼图切片)来表示相关性程度
if corr_val != 0:
# 将相关系数转换为角度(0到360度)
# 绝对值越大,扇形角度越大
angle = abs(corr_val) * 360
# 创建指定半径的楔形
# width=radius 使楔形填充整个圆形
# 颜色根据相关系数值在颜色映射中的位置确定
wedge = Wedge((i, j), radius, 0, angle,
width=radius,
color=cmap((corr_val + 1) / 2))
ax.add_artist(wedge)
# 设置刻度和坐标轴范围,为圆形添加适当的边距
padding = radius * 1.5 # 额外的边距,使图形更美观
ax.set_xticks(range(n_vars)) # 设置x轴刻度位置
ax.set_yticks(range(n_vars)) # 设置y轴刻度位置
# 设置x轴标签,旋转45度并右对齐,字体大小14
ax.set_xticklabels(corr_matrix.columns, rotation=45, ha='right', fontsize=14)
# 设置y轴标签,字体大小14
ax.set_yticklabels(corr_matrix.columns, fontsize=14)
# 设置x轴和y轴的范围,考虑边距
ax.set_xlim(-padding, n_vars - 1 + padding)
ax.set_ylim(n_vars - 1 + padding, -padding) # y轴反向,使矩阵从上到下排列
# 添加颜色条
# 创建可映射的颜色对象,设置颜色映射和数值范围(-1到1)
sm = plt.cm.ScalarMappable(cmap=cmap, norm=plt.Normalize(-1, 1))
sm.set_array([]) # 设置空数组
# 添加颜色条到图形,shrink=0.8使颜色条稍微缩小
cbar = plt.colorbar(sm, ax=ax, shrink=0.8)
cbar.set_label('Correlation Coefficient', fontsize=14) # 设置颜色条标签
# 设置标题和布局
plt.title('Correlation Matrix', fontsize=18) # 设置图形标题
plt.tight_layout() # 自动调整布局,防止标签被截断
return fig, ax # 返回图形和坐标轴对象
# 使用示例数据
# 从Excel文件读取数据
df = pd.read_excel(r'E:\PythonProjects\experiments_figures\experiments_figures\相关性热图\data.xlsx',
engine='openpyxl', sheet_name='Sheet1', header=0)
# 计算皮尔逊相关系数矩阵
# method='pearson'指定使用皮尔逊相关系数(默认就是pearson)
corr = df.corr(method='pearson')
# 创建相关性图,设置图形大小为10x8英寸,圆形半径为0.4
fig, ax = correlation_pie_plot(corr, figsize=(10, 8), radius=0.4)
# 保存图片为600 DPI的PNG格式
plt.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\相关性热图\相关性热图.png',
dpi=600,
bbox_inches='tight',
pad_inches=0.2)
# 显示图表
plt.tight_layout()
plt.show()

9 边际直方图
# 导入必要的库
import pandas as pd
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
'''读取xlsx文件'''
data = pd.read_excel(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图/data.xlsx',
engine='openpyxl',
sheet_name='Sheet1',
header=0)
# 输出前5行数据
print(data.head())
# 定义要分析的变量
x = 'F2' # x轴变量
y = 'target' # y轴变量
# 定义一套美观的紫色系配色方案
color_scheme = {
'hex': '#6A0DAD', # 深紫色
'kde_fill': '#9370DB', # 中紫色
'reg': '#BA55D3', # 亮紫色
'kde_contour': '#8A2BE2',# 紫蓝色
'hist': '#9932CC' # 暗紫色
}
#%%
"绘制多边形分布图形"
sns.set(style="white", font_scale=2.5,
rc={"axes.linewidth": 2, "axes.edgecolor": "black"},
font=['Times New Roman'])
g = sns.jointplot(x=x, y=y,
data=data,
color=color_scheme['hex'],
marginal_kws=dict(bins=30,
kde=True,
color=color_scheme['hex']
),
kind='hex',
joint_kws={'gridsize': 30}
)
g.fig.set_size_inches(12, 10)
g.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图\hex_plot.png', dpi=600, format='png')
plt.show()
#%%
"绘制核密度分布图形"
sns.set(style="white", font_scale=2.5,
rc={"axes.linewidth": 2, "axes.edgecolor": "black"},
font=['Times New Roman'])
# 移除了被contourf忽略的linewidths参数,消除警告
g = sns.jointplot(x=x, y=y,
data=data,
color=color_scheme['kde_fill'],
kind='kde',
marginal_kws=dict(fill=True,
color=color_scheme['kde_fill']),
joint_kws={'gridsize': 15, 'fill': True} # 移除linewidths参数
)
g.fig.set_size_inches(12, 10)
g.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图\kde_fill_plot.png', dpi=600, format='png')
plt.show()
#%%
"绘制散点分布图形"
sns.set(style="white", font_scale=2.5,
rc={"axes.linewidth": 2, "axes.edgecolor": "black"},
font=['Times New Roman'])
g = sns.jointplot(x=x, y=y,
data=data,
color=color_scheme['reg'],
kind='reg'
)
g.fig.set_size_inches(12, 10)
g.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图\scatter_reg_plot.png', dpi=600, format='png')
plt.show()
#%%
"绘制密度分布图形"
sns.set(style="white", font_scale=2.5,
rc={"axes.linewidth": 2, "axes.edgecolor": "black"},
font=['Times New Roman'])
g = sns.jointplot(x=x, y=y,
data=data,
color=color_scheme['kde_contour'],
kind='kde',
levels=12,
linewidths=3
)
# 调整边际图的KDE线宽
g.ax_marg_x.lines[0].set_linewidth(3)
g.ax_marg_y.lines[0].set_linewidth(3)
g.fig.set_size_inches(12, 10)
g.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图\density_contour_plot.png', dpi=600, format='png')
plt.show()
#%%
"绘制直方点分布图形"
sns.set(style="white", font_scale=2.5,
rc={"axes.linewidth": 2, "axes.edgecolor": "black"},
font=['Times New Roman'])
g = sns.jointplot(x=x, y=y,
data=data,
color=color_scheme['hist'],
kind='hist'
)
g.fig.set_size_inches(12, 10)
g.savefig(r'E:\PythonProjects\experiments_figures\experiments_figures\边际直方图\histogram_plot.png', dpi=600, format='png')
plt.show()




