当前位置:首页>python>科研小白开箱即用的多目标优化方法——Python灰色关联分析

科研小白开箱即用的多目标优化方法——Python灰色关联分析

  • 2026-10-11 08:35:47
科研小白开箱即用的多目标优化方法——Python灰色关联分析
多指标方案优选、工艺参数优化、综合评价……灰色关联分析(GRA)都能轻松搞定。本文不仅讲清楚原理,还附上一份可直接运行的Python代码,内含顶刊风格图表,帮你一键完成计算与可视化。

一、什么是灰色关联分析?

灰色关联分析(Grey Relational Analysis, GRA)是灰色系统理论中的一种多因素决策方法。它的核心思想是:通过比较各方案与“理想最优方案”在几何形状上的相似程度,来判断方案的优劣。关联度越大,方案越优。

适用场景:

  • 农业试验中不同处理组合的综合评价

  • 工艺参数(温度、时间、浓度等)的多指标优化

  • 供应商选择、项目评估等小样本决策问题

优点:

  • 对样本量要求低(≥3即可)

  • 不要求数据服从特定分布

  • 计算过程透明,可解释性强


二、代码功能速览

下面这份完整的Python代码实现以下功能:

  1. 读取Excel数据,按处理组合分组求均值

  2. 执行完整的灰色关联分析(标准化→参考序列→关联系数→关联度→排名)

  3. 将所有中间计算过程导出到Excel(6张工作表)

  4. 生成4张专业图表(排名柱状图、交互热力图、指标箱线图、关联系数热图)

  5. 图表样式可定制:热力图改为绿色渐变,箱线图改为双色渐变+缺口箱体

代码保存路径:E:\DataAnalysis\GRA(自动创建)


三、完整代码与逐段解读

🧩 0. 导入所需库

import osimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport seaborn as snsfrom matplotlib.colors import LinearSegmentedColormap
  • os:创建文件夹

  • numpy、pandas:数据处理

  • matplotlib、seaborn:绘图

  • LinearSegmentedColormap:自定义渐变色


🗂️ 1. 路径设置

input_path = r"E:\DataAnalysis\Data.xlsx"save_dir = r"E:\DataAnalysis\GRA"os.makedirs(save_dir, exist_ok=True)os.makedirs(os.path.join(save_dir, "plots"), exist_ok=True)
指定输入Excel路径和输出文件夹,自动创建目录。你需要修改 input_path 为自己的文件路径。

🎨 2. 自定义配色方案

代码中定义了三种渐变色,用于不同图表:

# --- 粉色系渐变(薄雾粉→晶石紫)---pink_palette = [    "#F9EDF4",  # 薄雾粉    "#EDC9DD",  # 樱花粉    "#E0A5C7",  # 蔷薇粉    "#D180B1",  # 胭脂粉    "#C15B9B",  # 浆果紫    "#B02F86"   # 晶石紫]custom_pink_cmap = LinearSegmentedColormap.from_list("custom_pink", pink_palette, N=256)# --- 绿色系单色渐变(森林绿→晨雾白绿)---green_palette = [    "#D4E7CF",  # 晨雾白绿    "#B8D8B0",  # 薄荷雾绿    "#9CC891",  # 嫩苗绿    "#7FB873",  # 新叶绿    "#61A855"   # 森林绿]custom_green_cmap = LinearSegmentedColormap.from_list("custom_green", green_palette, N=256)# --- 双色渐变(森林绿→浆果红)---dual_palette = [    "#61A855",  # 森林绿    "#7FB873",  # 新叶绿    "#9CC891",  # 嫩苗绿    "#B8D8B0",  # 薄荷雾绿    "#D4E7CF",  # 晨雾白绿    "#FFD6D4",  # 贝壳粉    "#FFBAB8",  # 蜜桃粉    "#FE9E9D",  # 珊瑚粉    "#F98082",  # 草莓红    "#F36069"   # 浆果红]custom_dual_cmap = LinearSegmentedColormap.from_list("custom_dual", dual_palette, N=256)
可以根据需要修改这些十六进制颜色值,调出专属配色。

⚙️ 3. 全局绘图风格设置

plt.rcParams.update({    "font.family": ["Arial", "SimHei"],    "font.size": 10,    "axes.titlesize": 12,    "axes.labelsize": 11,    "xtick.labelsize": 9,    "ytick.labelsize": 9,    "legend.fontsize": 9,    "figure.dpi": 300,    "savefig.dpi": 600,    "savefig.bbox": "tight",    "axes.spines.top": False,    "axes.spines.right": False,    "grid.alpha": 0.3,    "grid.linestyle": "--",    "axes.unicode_minus": False})
  • 中英文字体兼容(Arial + SimHei)

  • 高分辨率输出(600 dpi),符合期刊要求

  • 去掉顶部和右侧边框,网格线半透明虚线,更现代


📥 4. 读取数据

df = pd.read_excel(input_path, sheet_name="Sheet1")df_mean = df.groupby(["Treatment", "Factor1", "Factor2"]).mean().reset_index()indicators = [col for col in df_mean.columns if col not in ["Treatment", "Factor1", "Factor2"]]data_matrix = df_mean[indicators].valuestreatments = df_mean["Treatment"].valuesT = df_mean["Factor1"].valuesW = df_mean["Factor2"].values

假设Excel包含以下列:

  • Treatment:处理组合名称(如“T1W2”)

  • Factor1 和 Factor2:两个实验因素

  • 其余列均为测量指标(Ind1, Ind2, …)

代码先按三个分组变量求均值(若没有重复测量,均值即原值),然后提取指标矩阵和标签。


🧮 5. 灰色关联分析核心函数

def gray_relation_analysis(data, rho=0.5):    data_norm = (data - data.min(axis=0)) / (data.max(axis=0) - data.min(axis=0) + 1e-8)    ref = data_norm.max(axis=0)    diff = np.abs(data_norm - ref)    min_diff = diff.min()    max_diff = diff.max()    gamma = (min_diff + rho * max_diff) / (diff + rho * max_diff)    grade = gamma.mean(axis=1)    return data_norm, ref, diff, gamma, grade

参数解释:

  • rho:分辨系数,通常取0.5,用于调节关联系数之间的差异。

  • 标准化方法:极差归一化,使各指标范围变为[0,1]。

  • 参考序列:取每个指标归一化后的最大值(若指标越小越好,可将max改为min)。

  • 关联系数:公式为 (min_diff + ρ·max_diff) / (diff + ρ·max_diff),反映每个方案每个指标与最优值的接近程度。

  • 关联度:每个方案所有指标关联系数的算术平均值。

调用函数,并按照关联度降序排序:

data_norm, ref_seq, diff_matrix, gamma_matrix, gray_grade = gray_relation_analysis(data_matrix)rank_idx = np.argsort(gray_grade)[::-1]sorted_treat = treatments[rank_idx]sorted_grade = gray_grade[rank_idx]sorted_T = T[rank_idx]sorted_W = W[rank_idx]

📎 6. 导出完整计算过程到Excel

with pd.ExcelWriter(os.path.join(save_dir, "GRA_计算全过程.xlsx"), engine="openpyxl") as writer:    df_mean.to_excel(writer, sheet_name="1_原始均值数据", index=False)    pd.DataFrame(data_norm, columns=indicators, index=treatments).to_excel(writer, sheet_name="2_标准化数据")    pd.DataFrame(ref_seq, index=indicators, columns=["最优参考序列"]).to_excel(writer, sheet_name="3_参考序列")    pd.DataFrame(diff_matrix, columns=indicators, index=treatments).to_excel(writer, sheet_name="4_差异矩阵")    pd.DataFrame(gamma_matrix, columns=indicators, index=treatments).to_excel(writer, sheet_name="5_关联系数矩阵")    result_df = pd.DataFrame({        "排名": range(1, len(sorted_treat)+1),        "处理组合": sorted_treat,        "Factor1(T)": sorted_T,        "Factor2(W)": sorted_W,        "灰色关联度": np.round(sorted_grade, 4)    })    result_df.to_excel(writer, sheet_name="6_关联度最终排名", index=False)
一张Excel内包含6个工作表,从原始数据到最终排名一目了然,方便论文附录或同行复核。

📊 7. 绘图(重点:样式定制)

图1:关联度排名柱状图

plt.figure(figsize=(10, 6))bar_colors = sns.color_palette(pink_palette, n_colors=len(sorted_treat))bars = plt.barh(sorted_treat[::-1], sorted_grade[::-1], color=bar_colors[::-1], height=0.7, edgecolor="white", linewidth=0.5)plt.barh(sorted_treat[0], sorted_grade[0], color="#61A855", height=0.7, label=f'最优组合:{sorted_treat[0]}')plt.xlabel("灰色关联度", fontweight="bold")plt.ylabel("处理组合", fontweight="bold")plt.title("各处理组合灰色关联度排名", fontweight="bold", pad=12)plt.xlim(left=np.min(sorted_grade)*0.9, right=np.max(sorted_grade)*1.05)plt.grid(axis='x')plt.legend(frameon=False)plt.tight_layout()plt.savefig(os.path.join(save_dir, "plots", "01_关联度排名柱状图.png"))plt.close()

图2:T×W交互热力图

heat_data = pd.DataFrame({"T": T, "W": W, "灰色关联度": gray_grade})heat_pivot = heat_data.pivot_table(index="T", columns="W", values="灰色关联度", aggfunc="mean")plt.figure(figsize=(8, 6))# 仅修改cmap为绿色系单色渐变,其余参数完全不变ax = sns.heatmap(heat_pivot, annot=True, cmap=custom_green_cmap, fmt=".4f",                  linewidths=0.8, linecolor="white", cbar_kws={"label": "灰色关联度"})plt.title("T×W处理组合关联度热力图", fontweight="bold", pad=12)ax.set_xlabel("Factor2 (W)", fontweight="bold")ax.set_ylabel("Factor1 (T)", fontweight="bold")plt.tight_layout()plt.savefig(os.path.join(save_dir, "plots", "02_TW交互热力图.png"))plt.close()

图3:各指标关联系数箱线图

plt.figure(figsize=(12, 6))# 核心修改:# 1. palette改为双色渐变# 2. notch=True 开启顶刊流行的缺口箱体(展示中位数置信区间,更专业美观)# 3. 优化箱体线条、宽度、异常值样式,提升质感sns.boxplot(    data=gamma_matrix,    palette=dual_palette,    notch=True,          # 缺口箱体    linewidth=1.2,       # 箱体描边加粗    width=0.7,           # 箱体宽度优化    fliersize=4,         # 异常值点大小    flierprops={        "marker": "o",        "markerfacecolor": "#B02F86",        "markeredgecolor": "white",        "alpha": 0.8    })plt.xticks(ticks=range(len(indicators)), labels=[f"Ind{i+1}" for i in range(len(indicators))], rotation=45)plt.xlabel("测量指标", fontweight="bold")plt.ylabel("关联系数", fontweight="bold")plt.title("各指标关联系数分布", fontweight="bold", pad=12)plt.tight_layout()plt.savefig(os.path.join(save_dir, "plots", "03_指标关联系数箱线图.png"))plt.close()

图4:关联系数矩阵热图

plt.figure(figsize=(14, 8))gamma_df = pd.DataFrame(gamma_matrix, index=treatments, columns=[f"Ind{i+1}" for i in range(len(indicators))])ax = sns.heatmap(gamma_df, annot=True, cmap=custom_pink_cmap, fmt=".3f",                  linewidths=0.5, linecolor="white", cbar_kws={"label": "关联系数"})plt.title("关联系数矩阵热图", fontweight="bold", pad=12)ax.set_xlabel("测量指标", fontweight="bold")ax.set_ylabel("处理组合", fontweight="bold")plt.tight_layout()plt.savefig(os.path.join(save_dir, "plots", "04_关联系数矩阵热图.png"))plt.close()

📢 8. 控制台输出结果

print("="*60)print("✅ 灰色关联分析完成!所有文件已自动保存")print(f"📂 文件保存路径:{save_dir}")print("="*60)print(f"🏆 最优处理组合:{sorted_treat[0]}")print(f"📊 最优组合关联度:{round(sorted_grade[0], 4)}")print("="*60)print("📋 关联度前5名组合:")for i in range(5):    print(f"第{i+1}名:{sorted_treat[i]} | 关联度:{round(sorted_grade[i], 4)}")print("="*60)print("🖼️ 图表调整说明:")print("  1. 02_TW交互热力图 → 森林绿单色渐变")print("  2. 03_指标关联系数箱线图 → 双色渐变+顶刊流行缺口箱体")print("="*60)

三、总结

  • ✅ 开箱即用:只需准备一张Excel表,修改路径即可运行

  • ✅ 过程透明:所有中间结果导出到Excel,便于核查

  • ✅ 图表精美:顶刊风格配色、缺口箱体、高分辨率输出

  • ✅ 高度可定制:颜色、分辨系数、指标方向均可轻松修改

无论你是科研人员、数据分析师,还是学生,这套代码都能帮助你快速完成多指标方案优选任务。

赶快用你的代码和数据试试吧! 🚀


如果你觉得有帮助的话,欢迎点赞、收藏、转发!有任何问题或改进建议,也欢迎在评论区交流。

内容包含AI辅助创作,如有侵权,请联系删除。

最新文章

随机文章