评价方法-秩和比

基本概念

  • 秩:rank,秩次,序数
  • 秩和:秩次的和
  • 平均秩次:将数据从小到大排序并编号之后序号的平均数
  • 通过秩转换获得无量纲的统计量
  • 秩和比的精髓不在前半部分的根据秩次为评价对象排序,而在于后半部分的正态离差分档。做综合评价时,可以利用TOPSIS等更加细腻的方法为评价对象排序,再与秩和比法结合进行分档。

算法过程

  1. 生成原始数据表
  2. 排序
  3. 编秩(整(秩)次秩和比法/非整(秩)次秩和比法)
  4. 计算秩和比(RSR)或加权秩和比(WRSR),并根据RSR值的大小,对评价对象进行综合排序 (到此步骤为直接排序,下列步骤从正态分布角度进行分档排序)
  5. 生成RSR频数分布表,列出各组RSR的频数及各组累计频数
  6. 确定各组RSR的秩次范围及平均秩次
  7. 计算累计频率,校正
  8. 将累计频率换算为概率单位Probit(累计频率对应的标准正态离差+ 5)(probit transformation概率单位法)
  9. 以Probit为自变量,RSR为因变量构建回归方程(检验回归方程拟合效果/回归系数是否有显著统计意义,R2/P值/F值)
  10. 按照回归方程所推算的RSR估计值对评价对象进行分档排序(分档依据为标准正态离差,范围一般设定为-3~3),具体分档数可根据实际情况决定 (要求各档差异有统计学意义,包括Bartlett检验)

 

Code

import pandas as pd
import numpy as np
import statsmodels.api as sm
import scipy.stats 


def rsr(data, weight=None, threshold=None, full_rank=True):
	Result = pd.DataFrame()
	n, m = data.shape

	# 对原始数据编秩
	if full_rank:
		for i, X in enumerate(data.columns):
			Result[f'X{str(i + 1)}:{X}'] = data.iloc[:, i]
			Result[f'R{str(i + 1)}:{X}'] = data.iloc[:, i].rank(method="average")
	else:
		for i, X in enumerate(data.columns):
			Result[f'X{str(i + 1)}:{X}'] = data.iloc[:, i]
			Result[f'R{str(i + 1)}:{X}'] = 1 + (n - 1) * (data.iloc[:, i].max() - data.iloc[:, i]) / (data.iloc[:, i].max() - data.iloc[:, i].min())

	# 计算秩和比
	weight = 1 / m if weight is None else np.array(weight) / sum(weight)
	Result['RSR'] = (Result.iloc[:, 1::2] * weight).sum(axis=1) / n
	Result['RSR_Rank'] = Result['RSR'].rank(ascending=False)

	# 绘制 RSR 分布表
	RSR = Result['RSR']
	RSR_RANK_DICT = dict(zip(RSR.values, RSR.rank().values))
	Distribution = pd.DataFrame(index=sorted(RSR.unique()))
	Distribution['f'] = RSR.value_counts().sort_index()
	Distribution['Σ f'] = Distribution['f'].cumsum()
	Distribution[r'\bar{R} f'] = [RSR_RANK_DICT[i] for i in Distribution.index]
	Distribution[r'\bar{R}/n*100%'] = Distribution[r'\bar{R} f'] / n #根据累计频数算累计频率
	Distribution.iat[-1, -1] = 1 - 1 / (4 * n) #修正最后一项累计频率
	Distribution['Probit'] = 5 - stats.norm.isf(Distribution.iloc[:, -1])  #inverse survival function 将累计频率换算为概率单位

	# 计算回归方差并进行回归分析
	r0 = np.polyfit(Distribution['Probit'], Distribution.index, deg=1) #x,y
    model = sm.OLS(Distribution.index, sm.add_constant(Distribution['Probit']))#y,x
    result = model.fit()
    print(result.summary())
    #print(sm.OLS(Distribution.index, sm.add_constant(Distribution['Probit'])).fit().summary())

    
    # 残差检验
    z_error, p_error = stats.normaltest(result.resid.values) #tests the null hypothesis that a sample comes from a normal distribution
    print("残差分析:    ", p_error)
    
    
	if r0[1] > 0:
		print(f"\n回归直线方程为:y = {r0[0]} Probit + {r0[1]}")
	else:
		print(f"\n回归直线方程为:y = {r0[0]} Probit - {abs(r0[1])}")

	# 代入回归方程并分档排序
	Result['Probit'] = Result['RSR'].apply(lambda item: Distribution.at[item, 'Probit'])
	Result['RSR Regression'] = np.polyval(r0, Result['Probit'])
	threshold = np.polyval(r0, [2, 4, 6, 8]) if threshold is None else np.polyval(r0, threshold)
	Result['Level'] = pd.cut(Result['RSR Regression'], threshold, labels=range(len(threshold) - 1, 0, -1))  #Probit分组[(2, 4] < (4, 6] < (6, 8]]

	return Result, Distribution


def rsrAnalysis(data, file_name=None, **kwargs):
	Result, Distribution = rsr(data, **kwargs)
	file_name = 'RSR 分析结果报告.xlsx' if file_name is None else file_name + '.xlsx'
	Excel_Writer = pd.ExcelWriter(file_name)
	Result.to_excel(Excel_Writer, '综合评价结果')
	Result.sort_values(by='Level', ascending=False).to_excel(Excel_Writer, '分档排序结果')
	Distribution.to_excel(Excel_Writer, 'RSR分布表')
	Excel_Writer.save()

	return Result, Distribution


### 下面添加文件读取,然后调用rsr子函数就可以了,最后结果会自动输出到excel
#链接里面的是:
# 读取数据
data = pd.DataFrame({'产前检查率': [99.54, 96.52, 99.36, 92.83, 91.71, 95.35, 96.09, 99.27, 94.76, 84.80],
                     '孕妇死亡率': [60.27, 59.67, 43.91, 58.99, 35.40, 44.71, 49.81, 31.69, 22.91, 81.49],
                     '围产儿死亡率': [16.15, 20.10, 15.60, 17.04, 15.01, 13.93, 17.43, 13.89, 19.87, 23.63]},
                    index=list('ABCDEFGHIJ'), columns=['产前检查率', '孕妇死亡率', '围产儿死亡率'])
#因为下面两个是成本型指标,需要反向排序,所以他做了这个变换
data["孕妇死亡率"] = 1 / data["孕妇死亡率"]
data["围产儿死亡率"] = 1 / data["围产儿死亡率"]
# 下面是调用子函数进行秩和比几个步骤的计算
rsr(data)

Notes

Barlett检验:Bartlett检验是方差齐性检验(对两组样本的方差是否相同进行检验)的一种方法,其核心思想是通过求取不同组之间的卡方统计量,然后根据卡方统计量的值来判断组间方差是否相等。该方法极度依赖于数据是正态分布,如果数据非正态分布,则结果偏差很大;而Levene检验对正态分布没有要求

方差分析(ANOVA/F检验):

  • 用于两个及两个以上样本均数差别的显著性检验;而T检验只能分析两组(两个类别)数据间的差异;如果刚好两组,建议样本较少(小于100)时使用T检验,反之使用方差分析
  • 方差分析有一个重要的假设是方差齐性,因为方差分析是用来比较多组之间均值是否存在显著差异。那如果方差不一致,也就意味着值的波动程度是不一样的,如果此时均值之间存在显著差异,不能够说明一定是不同组间处理带来的,有可能是大方差带来大的波动;如果方差一样,也就意味着值的波动程度是一样的,在相同波动程度下,直接去比较均值,如果均值之间存在显著差异,那么可以认为是不同组间处理带来的。(另外两个假设是:每个样本的值服从正态分布;每个样本中的个体相互独立)

Reference

RSR(秩和比综合评价法)介绍及python3实现

秩和比法RSR

概率密度函数pdf

python 计算概率密度、累计分布、逆函数

probit与分位函数

scipy.stats与统计学(概率分布)

一元线性回归分析的t检验和f检验

 

你可能感兴趣的