SWARA-逐步权重评估比率分析
SWARA(Step-wise Weight Assessment Ratio Analysis,逐步权重评估比率分析)是一类典型的主观赋权方法。其基本思想是:先给指标建立重要性顺序,再令每个后续指标相对于前一指标给出“相对不重要程度” sj,随后逐步递推得到权重。
SWARA-逐步权重评估比率分析
1. 方法概述
SWARA(Step-wise Weight Assessment Ratio Analysis,逐步权重评估比率分析)是一类典型的主观赋权方法。其基本思想是:先给指标建立重要性顺序,再令每个后续指标相对于前一指标给出“相对不重要程度” \(s_j\),随后逐步递推得到权重。
但就本项目 具体的算法3/多指标评价/SWARA-逐步权重评估比率分析 的当前实现而言,该模块并不是“只输出 SWARA 权重”的独立赋权器,而是一个完整的:
- 指标类型处理;
- 标准化;
- SWARA 主观赋权;
- 加权求和评分;
- 排名;
- Excel、图表与复现脚本导出
的一体化评价模块。
结合 core/swara_calculator.py、ui/main_window.py、ui/methods_widget.py 与 ui/results_widget.py,当前模块存在两条输入路径:
- 正向流程:用户直接输入 SWARA 的 \(s_j\);
- 逆向流程:根据专家评分表反推指标顺序与 \(s_j\)。
设共有 \(m\) 个对象、\(n\) 个指标,原始决策矩阵记为
$$ X=(x_{ij})_{m\times n}, \quad i=1,2,\ldots,m, \quad j=1,2,\ldots,n \tag{1} $$
设 SWARA 排序后的指标序列记为
$$ \big(C_{(1)},C_{(2)},\ldots,C_{(n)}\big) \tag{2} $$
设最终权重向量为
$$ w=\big(w_{(1)},w_{(2)},\ldots,w_{(n)}\big)^\top, \quad w_{(j)}\ge 0, \quad \sum_{j=1}^{n}w_{(j)}=1 \tag{3} $$
项目最终结果表中的核心列为:
alternativescorerank
其中 score 越大表示对象越优,rank=1 表示最优对象。
需要特别说明:核心主计算函数仍命名为 calculate_topsis(),但它的真实计算内容已经是“SWARA 权重 + 加权求和评分”,并不是 TOPSIS。
2. 输入结构与项目流程
2.1 输入数据要求
上传页 ui/upload_widget.py 支持 .xlsx、.xls 与 .csv 文件,也支持示例数据。结合 utils/data_validator.py,当前项目对输入数据的要求为:
- 第 1 列为对象名称;
- 第 2 列及以后为指标列;
- 指标列必须全为数值;
- 指标列不允许空值;
- 对象名称不允许重复;
- 常数列不允许存在。
因此,进入 SWARA 主计算链的数据可表示为
$$ \mathcal{D}=\{A_i,\ x_{i1},x_{i2},\ldots,x_{in}\}_{i=1}^{m} \tag{4} $$
与前面已经完成的 StandardDeviation 模块不同,当前 SWARA 上传校验是 严格阻断式 的:
- 对象重复会直接报错;
- 常数列会直接报错;
- 不会只给 warning 后继续计算。
2.2 指标页与流程选择页
指标页 ui/indicators_widget.py 会收集:
selected_indicatorsindicator_typesstandard_values
当前支持三类指标:
- 正向指标;
- 负向指标;
- 适度指标。
适度指标在 UI 中必须显式输入标准值,且当前界面把数值 0 视为“未设置”。
在指标确认后,主窗口 ui/main_window.py 会进入流程选择页 FlowSelectWidget,要求用户在以下两条链路中二选一:
- 正向流程;
- 逆向流程。
2.3 正向流程
正向流程进入 methods_widget_forward,用户需要:
- 选择标准化方式;
- 按 SWARA 顺序输入各指标的相对重要度 \(s_j\)。
当前方法页的默认规则为:
- 第 1 个指标默认 \(s_1=0\);
- 其余指标默认 \(s_j=0.1\)。
这里有一个必须写清楚的项目实现约束:当前正向 UI 不提供指标拖拽重排功能。因此,正向流程中 SWARA 的指标顺序,默认取自
- 上传数据后的列顺序;
- 或用户勾选子集后保留下来的原始顺序。
也就是说,若论文或业务逻辑需要先对指标做“主观重要性排序”,当前正向 UI 的做法是:把数据列顺序本身视为 SWARA 顺序。
2.4 逆向流程
逆向流程进入 methods_widget_reverse。用户可以导入专家评分表,项目调用 derive_swara_order_and_s() 自动反推:
- 指标顺序;
- 每个指标的 \(s_j\);
- 专家权重归一化结果。
在方法页内部,逆向流程会把新的指标顺序刷新到表格中,并同步刷新 swara_s_values。
但需要非常谨慎地区分:
core/swara_calculator.py的逆向能力,是真正会重排selected_indicators的;- 当前
ui/main_window.py在最终启动计算时,传给ResultsWidget.start_calculation()的indicators仍然来自indicator_settings['selected_indicators']。
因此,当前 UI 逆向流程只有在“倒推顺序恰好与原始指标顺序一致”时,才能与核心逆向链路完全一致。若研究者需要严格按倒推顺序参与计算,应该以核心 derive_from_expert_scores() 的调用口径为准。
3. 指标类型处理与标准化口径
3.1 中间矩阵定义
设经过方向处理但尚未完成最终标准化的中间矩阵记为
$$ U=(u_{ij})_{m\times n} \tag{5} $$
3.2 正向指标
若第 \(j\) 个指标为正向指标,则程序直接保留原值:
$$ u_{ij}=x_{ij} \tag{6} $$
3.3 负向指标
若第 \(j\) 个指标为负向指标,项目在 min-max 与 z-score 两种路径中的处理并不完全相同:
- 在
min-max路径中,直接按成本型公式归一化; - 在
z-score路径中,先做标准分数,再乘以 \(-1\) 翻转方向。
也就是说,SWARA 模块没有像 StandardDeviation 一样先构造
\(x_{\max}+x_{\min}-x\)
形式的镜像变量,而是在标准化阶段处理负向方向。
3.4 适度指标
若第 \(j\) 个指标为适度指标,程序先构造“越接近目标值越好”的接近度:
$$ u_{ij}=1-\frac{|x_{ij}-t_j|}{\max_{1\le i\le m}|x_{ij}-t_j|} \tag{7} $$
其中 \(t_j\) 为适度指标的目标值。
当前项目关于 \(t_j\) 的口径分为两层:
- 正常 UI 流程下,必须由用户手工输入,且不能为 0;
- 若直接调用核心且未提供
moderate_values,则核心回退为该列中位数。
因此,核心中的默认目标值可写为
$$ t_j= \begin{cases} \text{用户提供值}, & \text{若已提供}\\ \operatorname{median}(x_{\cdot j}), & \text{若未提供} \end{cases} \tag{8} $$
这意味着:当前 UI 和核心对适度指标默认值的行为并不完全一致。论文或说明文档若以主窗口界面为主,应写成“适度指标必须手工给定目标值”;若以核心 API 为主,则可补充“未给定时回退中位数”。
3.5 Z-score 标准化
当用户选择 z-score 时,程序先计算
$$ z_{ij}=\frac{u_{ij}-\mu_j}{\sigma_j} \tag{9} $$
其中
$$ \mu_j=\frac{1}{m}\sum_{i=1}^{m}u_{ij} \tag{10} $$
$$ \sigma_j=\sqrt{\frac{1}{m}\sum_{i=1}^{m}(u_{ij}-\mu_j)^2} \tag{11} $$
这里使用的是 numpy.nanstd 的默认口径,即总体标准差。
若第 \(j\) 个指标为负向指标,则程序进一步做方向翻转:
$$ z_{ij}\leftarrow -z_{ij} \tag{12} $$
随后再统一拉回到 \([0,1]\) 区间:
$$ n_{ij}=\frac{z_{ij}-z_j^{\min}}{z_j^{\max}-z_j^{\min}} \tag{13} $$
若 \(\sigma_j\) 或分母非常接近 0,代码会把它替换为 1,从而使该列最终变成全 0 列。
3.6 Min-Max 标准化
当用户选择 min-max 时:
对正向指标与适度指标,程序采用
$$ n_{ij}=\frac{u_{ij}-u_j^{\min}}{u_j^{\max}-u_j^{\min}} \tag{14} $$
对负向指标,程序采用
$$ n_{ij}=\frac{u_j^{\max}-u_{ij}}{u_j^{\max}-u_j^{\min}} \tag{15} $$
若分母非常接近 0,代码同样把分母替换为 1,因此常数列会退化为全 0 列。
3.7 最终标准化矩阵
综上,当前 SWARA 模块用于赋权和评分的统一标准化矩阵记为
$$ N=(n_{ij})_{m\times n} \tag{16} $$
项目不会分别为“赋权阶段”和“评分阶段”构造两套不同矩阵,而是直接在 \(N\) 上完成 SWARA 权重应用与综合得分计算。
4. SWARA 权重计算
4.1 正向 SWARA 递推
对已经给定顺序的指标序列
$$ \big(C_{(1)},C_{(2)},\ldots,C_{(n)}\big) \tag{17} $$
设第 \(j\) 个指标相对于前一指标的相对重要度参数为 \(s_{(j)}\),则当前项目采用的 SWARA 递推公式为:
$$ q_{(1)}=1 \tag{18} $$
$$ q_{(j)}=\frac{q_{(j-1)}}{1+s_{(j)}}, \quad j=2,3,\ldots,n \tag{19} $$
最终权重为
$$ w_{(j)}=\frac{q_{(j)}}{\sum_{r=1}^{n}q_{(r)}} \tag{20} $$
这正是 SWARACalculator._swara_weights() 的实现。
4.2 逆向倒推指标顺序
在逆向流程中,项目首先读取专家评分表。设共有 \(K\) 位专家,第 \(k\) 位专家对第 \(j\) 个指标的评分记为 \(e_{kj}\),专家权重记为 \(\omega_k\),则加权汇总分定义为
$$ g_j=\sum_{k=1}^{K}\omega_k e_{kj} \tag{21} $$
其中
$$ \omega_k\ge 0, \quad \sum_{k=1}^{K}\omega_k=1 \tag{22} $$
若用户没有传入专家权重,则:
- 若评分表存在
专家权重/权重/weight/Weight列,则自动读取; - 否则回退为等权。
若专家权重和不大于 0,程序也会回退为等权。
随后,项目按 \(g_j\) 从大到小排序,得到逆向推导的指标序列
$$ g_{(1)}\ge g_{(2)}\ge \cdots \ge g_{(n)} \tag{23} $$
4.3 逆向倒推 \(s_j\)
在顺序确定后,项目并不是让用户再输入 \(s_j\),而是直接由相邻指标汇总分之比推导:
$$ s_{(1)}=0 \tag{24} $$
$$ s_{(j)}=\frac{g_{(j-1)}}{g_{(j)}}-1, \quad j=2,3,\ldots,n \tag{25} $$
但实际代码还会做区间裁剪,因此完整口径为
$$ s_{(j)}=\min\left(10,\ \max\left(0,\frac{g_{(j-1)}}{g_{(j)}}-1\right)\right) \tag{26} $$
随后再把式(26)带回式(18)至式(20)完成 SWARA 权重计算。
5. 综合得分与排序
5.1 加权求和得分
得到权重向量后,当前项目直接采用加权求和计算对象得分:
$$ S_i=\sum_{j=1}^{n}n_{ij}w_j \tag{27} $$
矩阵形式可写为
$$ S=Nw \tag{28} $$
因此,本项目中的 SWARA 不再额外叠加 TOPSIS、VIKOR 或其他排序模型,而是把 SWARA 当作权重来源后,直接完成线性综合评价。
5.2 排名规则
设第 \(i\) 个对象的综合得分为 \(S_i\),则排名规则为
$$ R_i=\operatorname{rank}_{\downarrow}(S_i) \tag{29} $$
代码实现对应 pandas.rank(ascending=False, method="min")。因此,若存在并列得分,则会采用“最小名次”规则。
最终结果表按 rank 升序排序输出。
6. 输出结构、导出内容与复现
6.1 结果对象与结果字典
核心类 SWARACalculator 在计算完成后会生成 SwaraResult,其中包括:
normalizedweightsscoresparamschartslast_output
同时,get_results() 返回统一结果字典,包含:
raw_dataprocessed_datastep_resultsfinal_resultschartsparameters
但需要注意:该结果字典的结构比前面的 StandardDeviation 模块更简化。例如:
raw_data只记录n_rows与indicators;processed_data["normalized"]直接保存 DataFrame;final_results["weights"]与step_results["weights"]都是DataFrame(weight)。
6.2 Excel 工作表
save_results() 当前固定导出以下工作表:
ParametersNormalizedWeightsScoresRankingCharts
其中:
Normalized以对象名称为行索引;Weights以指标名为行索引,列名为weight;Scores保存alternative/score/rank;Ranking只保留alternative/rank。
6.3 图表输出
当前版本默认生成两张图:
- 权重横向条形图
*_weights_bar.png - 综合得分横向条形图
*_score_bar.png
测试工具 swara_test_common.py 还会校验:
Charts表必须存在;- 图表路径必须存在;
- 图表路径不得重复。
6.4 输出目录与双重复现脚本
结果页 ui/results_widget.py 会先建立带“正向/逆向”标签的时间戳目录:
SWARA-逐步权重评估比率分析分析结果_正向_时间戳
或
SWARA-逐步权重评估比率分析分析结果_逆向_时间戳
随后 core/swara_calculator.py 的 save_results() 会在该目录下再写出:
- 结果 Excel;
- 图表;
repro_swara.py;repro_inputs/input_snapshot.csv。
此外,结果页按钮“导出复现代码”还会额外生成一份 UI 层脚本:
repro_topsis_时间戳.py
因此,当前 SWARA 模块实际上存在两类复现脚本:
- 核心导出脚本
repro_swara.py - UI 页面导出脚本
repro_topsis_*.py
前者由核心 save_results() 自动生成,后者由结果页按钮显式生成。
6.5 分层计算
结果页还支持“仅用部分指标再计算一次”的附加功能。用户可以在指标列表中勾选子集后调用 calculate_partial_topsis()。
该功能属于当前项目额外提供的工程化能力,并不是 SWARA 经典方法本身的必要组成部分。
7. 与代码实现的对应关系
7.1 项目并不是“纯赋权”,而是直接输出综合排序
经典 SWARA 常被用作其他多指标模型的权重获取步骤。但本项目在获得 SWARA 权重后,直接采用式(27)的加权求和得到综合得分和排名,因此这里的 SWARA 是一个完整评价模块。
7.2 正向流程默认把数据列顺序当作 SWARA 顺序
这一点在论文说明中必须单独写明。当前正向 UI 不支持拖拽排序,因此
- 上传数据后的指标列顺序;
- 或选中子集后的保留顺序
就构成了 SWARA 的先验重要性顺序。
7.3 核心支持逆向重排,但当前 UI 逆向链路存在顺序约束
核心 derive_from_expert_scores() 会把 selected_indicators 直接重排为倒推出的顺序,这是完整逆向 SWARA 的标准实现。
但当前主窗口在真正发起计算时,仍然优先使用 indicator_settings['selected_indicators'] 作为参与计算的指标顺序。因此,若倒推顺序与原始顺序不同,当前 UI 逆向链路未必完全等价于核心逆向链路。
从代码口径上讲:
- 论文若说明“核心算法实现”,可以写成支持逆向重排;
- 若说明“当前 UI 主流程”,则应补充这一顺序约束。
7.4 核心保留了 custom_weights 覆盖分支,但当前主流程并不以此为主
SWARACalculator 中确实保留了:
set_weights()custom_weights
这一套“直接覆盖权重”的分支。若 custom_weights 非空,核心会优先对其归一化,并跳过 SWARA 递推权重。
但当前方法页 confirm_settings() 固定写入
weight_method='swara'
而主窗口 start_calculation() 也没有把 self.custom_weights 注入 ResultsWidget.start_calculation()。因此,当前项目的标准 UI 路径应以 SWARA 原生权重为准,而不应把“自定义权重”写成默认主流程。
8. 项目回归测试口径
当前 SWARA 模块已配套如下测试:
Z冒烟测试/test_swara_smoke.pyZ冒烟测试/test_swara_baseline.pyZ冒烟测试/test_swara_ui_flow.py
并有增强回归报告:
Z冒烟测试/SWARA-逐步权重评估比率分析_增强回归与UI链路报告_20260310.md
8.1 正向基线
基线数据对象为 A, B, C, D,指标为 Cost, Benefit, Risk,其中:
Cost为负向指标;Benefit为正向指标;Risk为负向指标。
正向 SWARA 设定为
$$ s_{\text{Cost}}=0,\quad s_{\text{Benefit}}=0.2,\quad s_{\text{Risk}}=0.4 \tag{30} $$
则期望权重向量为
$$ w= \big( 0.4117647059,\ 0.3431372549,\ 0.2450980392 \big)^\top \tag{31} $$
对应对象排序为
$$ C \succ B \succ D \succ A \tag{32} $$
对应综合得分为
$$ \big( 0.6405228758,\ 0.5882352941,\ 0.4354575163,\ 0.3970588235 \big) \tag{33} $$
8.2 逆向基线
逆向基线中,专家评分表倒推出的指标顺序为
$$ \big(\text{Cost},\ \text{Benefit},\ \text{Risk}\big) \tag{34} $$
倒推出的 \(s_j\) 为
$$ \big( 0,\ 0.0506329114,\ 0.4905660377 \big) \tag{35} $$
相应权重向量为
$$ w= \big( 0.3860465116,\ 0.3674418605,\ 0.2465116279 \big)^\top \tag{36} $$
对应对象排序仍为
$$ C \succ B \succ D \succ A \tag{37} $$
对应综合得分为
$$ \big( 0.6310077519,\ 0.6139534884,\ 0.4360465116,\ 0.3806201550 \big) \tag{38} $$
8.3 测试所验证的工程行为
当前测试除验证数值结果外,还额外验证:
- 权重和为 1;
save_results()产出的目录名包含“正向/逆向”标签;- Excel 至少包含
Parameters/Normalized/Weights/Scores/Ranking/Charts; repro_swara.py可执行并能再次产出结果;- UI 导出的
repro_topsis_*.py可以成功生成; - UI 流程可从首页进入结果页,并在完成后重置回首页。
因此,上述数值和导出口径可以直接作为当前项目 SWARA 模块撰写论文说明、系统说明和复现实验文档时的代码依据。
9. 论文写作模板
9.1 方法描述模板
“本文采用 SWARA 方法确定指标权重,并在此基础上完成综合评价。首先根据指标属性对原始数据进行标准化处理,得到统一标准化矩阵 \(N\)(式(9)–式(16))。随后,依据研究场景采用正向流程或逆向流程确定指标顺序与相对重要度参数 \(s_j\):正向流程由研究者直接给出 \(s_j\),逆向流程则根据专家评分表反推指标顺序与 \(s_j\)(式(21)–式(26))。在获得 SWARA 权重后,采用加权求和模型计算各对象综合得分 \(S_i\)(式(27)–式(28)),并按得分降序进行排序(式(29))。”
9.2 结果解释模板
结果部分可写为:SWARA 结果表不仅给出了各指标权重,还反映了权重背后的主观排序逻辑。若采用正向流程,则指标列顺序本身代表先验重要性顺序;若采用逆向流程,则权重由专家评分表反推得到。在综合评价阶段,\(S_i\) 越大表示对象整体表现越优。研究中应同时解释两个层面:一是指标顺序与 \(s_j\) 的设定依据,二是最终权重如何影响对象得分与排序结果。
9.3 表格标题模板
- 表 1 SWARA 指标顺序与相对重要度参数表
- 表 2 SWARA 指标权重结果表
- 表 3 各对象综合得分与排名结果表
- 表 4 逆向 SWARA 专家评分汇总结果表
- 表 5 正向与逆向 SWARA 结果对比表
9.4 图表题注模板
- 图 1 SWARA 指标权重条形图。
- 图 2 SWARA 各对象综合得分图。
9.5 表格示例
表 1 SWARA 指标权重结果
| 指标 | 顺序 | \(s_j\) | 权重 |
|---|---|---|---|
| Cost | 1 | 0 | |
| Benefit | 2 |
表注:权重按式(18)–式(20)递推计算;逆向流程下 \(s_j\) 的倒推见式(24)–式(26)。
表 2 SWARA 综合评价结果
| 对象 | 综合得分 \(S_i\) | 排名 |
|---|---|---|
| A | ||
| B |
表注:综合得分 \(S_i\) 按式(27)计算,取值越大表示对象越优。
10. 单篇终审补充
10.1 图题与表题对齐建议
Parameters表可写为:表X SWARA 参数设置表。Normalized表可写为:表X SWARA 标准化矩阵表。Weights表可写为:表X SWARA 指标权重表。Scores表可写为:表X SWARA 综合得分表。Ranking表可写为:表X SWARA 排名结果表。Charts表可写为:表X SWARA 图表索引表。*_weights_bar.png建议写为:图X SWARA 指标权重图。*_score_bar.png建议写为:图X SWARA 综合得分图。
10.2 终审说明
- 当前代表性结果目录建议同时保留正向与逆向两套,其中正向可采用
results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_正向_manual,逆向可采用results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_逆向_manual。 - 当前真实工作表为
Parameters/Normalized/Weights/Scores/Ranking/Charts。工作簿结构较精简,论文正文若需要解释指标顺序或 \(s_j\) 参数,应配合脚本参数快照,而不能只靠 xlsx 工作表。 - 当前稳定实体图文件与结果簿同级,而不在
charts/子目录下,典型文件名为..._weights_bar.png和..._score_bar.png。附录中的图文件说明应写清这一同级存放结构。 - 真实 repro 脚本统一命名为
repro_swara.py,并以REPRO_INPUT = 'repro_inputs/input_snapshot.csv'作为主输入快照;SRC_FILE在当前较新目录中通常为空字符串。附录应以REPRO_INPUT这一可移植口径为主。 - 当前结果目录会继续在
repro_outputs/results_时间戳/下生成复现结果。论文正文若只陈述主实验,应固定引用首层结果,不要把后续复现层混入主文。
10.3 全量强化补充
- 本轮按真实磁盘再次核对,算法目录为
具体的算法3/多指标评价/SWARA-逐步权重评估比率分析。建议继续保留正向与逆向两套代表目录:正向为具体的算法3/多指标评价/SWARA-逐步权重评估比率分析/results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_正向_manual,逆向为具体的算法3/多指标评价/SWARA-逐步权重评估比率分析/results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_逆向_manual。 - 正向主工作簿为
SWARA-逐步权重评估比率分析分析结果_20260321_051528.xlsx,逆向主工作簿为SWARA-逐步权重评估比率分析分析结果_20260321_051529.xlsx。两份工作簿结构一致,真实工作表均为Parameters、Normalized、Weights、Scores、Ranking、Charts。 - 当前图文件并不在
charts/子目录,而是与主工作簿同级直接存放:正向为..._weights_bar.png与..._score_bar.png,逆向亦然。这一点应明确写入附录路径说明。 - 当前
repro_swara.py中SRC_FILE = "",真正可移植输入由REPRO_INPUT = "repro_inputs/input_snapshot.csv"提供;该输入副本在正向、逆向两个目录中都实际存在。 - 正向目录下已有
repro_outputs/results_20260321_051529/...,逆向目录下已有repro_outputs/results_20260321_051530/...,且逆向目录还继续递归生成更深层结果。因此,这篇必须按“正向/逆向双主目录 + 双层以上 repro_outputs”结构来写。 - 工作簿本身不保留指标顺序和 \(s_j\) 的完整推导细节,若论文需要解释顺序来源,必须结合
repro_swara.py的参数快照,而不能只依赖 xlsx。
11. 软件实现核查补充(2026-07)
- 当前主结果目录应写作
具体的算法3/多指标评价/SWARA-逐步权重评估比率分析/results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_正向_manual与具体的算法3/多指标评价/SWARA-逐步权重评估比率分析/results/manual_check_20260321_01/SWARA-逐步权重评估比率分析分析结果_逆向_manual。 - 正文应围绕
Parameters、Normalized、Weights、Scores、Ranking、Charts来写。 - 图证应对应同级存放的
..._weights_bar.png与..._score_bar.png,并明确图文件不在charts/子目录中。 - 复现脚本应按
repro_swara.py + repro_inputs/input_snapshot.csv的口径说明;repro_outputs/里的多层结果只作为递归复现证据。