灰色关联分析,Python实现GRA(gray relation analysis)

灰色关联分析,Python实现GRA(gray relation analysis),第1张

灰色关联分析,Python实现GRA(gray relation analysis)

灰色关联分析法:
对于两个系统之间的因素,其随时间或不同对象而变化的关联性大小的量度,称为关联度。在系统发展过程中,若两个因素变化的趋势具有一致性,即同步变化程度较高,即可谓二者关联程度较高;反之,则较低。因此,灰色关联分析方法,是根据因素之间发展趋势的相似或相异程度,亦即“灰色关联度”,作为衡量因素间关联程度的一种方法。

灰色关联分析,公式网上都有很多,计算也不难,这里就不写公式。

之所以称为关联,是因为他只反映哪一个指标和要对比的指标最有关系,而不反映相关性。
他和相关性系数,没有一毛钱关系,也不对等。最后得出来的系数,也只是做一个排序。
不反映相关性,不反映相关性,不反映相关性。

灰色关联分析,是根据因素之间发展趋势的相似或相异程度,即“灰色关联度”,作为衡量因素间关联程度的方法

特点:

  1. 不需要自变量,参考变量服从正态分布,对样本数据没有要求,适合小样本数据。
  2. 能够将自变量和参考变量的关联性大小排序,从而得到重要性排序的评价,本身的关联度没有实际意义,比如得出关联度为0.95,这个数字只用排序,并不能像相关性0.95一样得出他们高度正相关。
  3. 缺点在于只能排序,不能得出确切的相关性,不属于相关性分析范畴,只归入综合评价方法里。

步骤:

  1. 确定参考指标和比较指标,一般参考指标放最开始的位置。
  2. 确定归一化(其实这里说归一化不太正确,但很多地方都说归一化,其实应该是消除量纲)方法,常见的有:
初值法增益型:每一个指标除以这个指标的第一个(初值)。成本型:第一个值除以每一个指标的每个值均值法增益型:每一个指标除以这个指标的均值。成本型:均值除以每一个指标的每个值区间变换法增益型:(指标减去最小值)除以(最大值减最小值) 。成本型:(最大值减去指标)除以(最大值减最小值)……

方法有很多,常见的就是初值和均值,增益型就是这个比较指标相对于参考指标越大越好,成本型就是越小越好,所以要把他们都转变成方向一致。

  1. 这时候的矩阵已经没有了量纲的影响,再用每个要比较的指标减去参考指标,一般参考放第一行,就都减去第一行的数据。这个地方要取绝对值,不能有负数,得到的矩阵一般记做Δ(k)
  2. 求两级最大差和最小差,即上面Δ(k)矩阵中的最大值,和最小值。记Δ(max),Δ(min)
  3. 得到关联系数矩阵:式子中的Δ(k)就是上面得到的绝对值后的矩阵
  4. 最后对每一个指标的向量求均值。就是最终的结果

下面是Python代码

# 最下面写了三个函数分别为gain,cost,level_,用于无量纲化,被GRA调用

def GRA(df,normaliza="initial",level=None,r=0.5):
    '''
    df : 二维数据,这里用dataframe,每一行是一个评价指标,要对比的参考指标放在第一行
    normaliza :["initial","mean"] 归一化方法,默认为初值,提供初值化或者均值化,其他方法自行编写
    level :为None默认增益型, 
            可取增益型"gain"(越大越好),成本型"cost"(越小越好),
            或者dataframe中的某一列,如level="level","level"是列名,这列中用数字1和0表示增益和成本型
    r : [0-1] 分辨系数  
            越大,分辨率越大; 越小,分辨率越小,一般取0.5
    '''
    # 判断类型
    if not isinstance(df,pd.Dataframe):
        df = pd.Dataframe(df)
        
    # 判断参数输入
    if (normaliza not in ["initial","mean"]) or (r<0 or r>1):
        raise KeyError("参数输入类型错误")
    
        # 增益型的无量纲化方法
    if level == "gain" or level == None:
        df_ = gain(df,normaliza)
        
        #成本性无量纲化方法
    elif level == "cost":
        df_ = cost(df,normaliza)
        
    else:# 有增益有成本性的无量纲化方法
        try:
            df.columns.get_loc(level) # 尝试获得这一列的列索引,判断输入的列名有没有,返回这个列的索引下标
        except:
            raise KeyError("表中没有这一列")
        df_ = level_(df,normaliza,level)
        df_.drop(level,axis=1,inplace=True)# 加的level这一列对总体没用,最后把这一列删除再做关联分析
        
    df_ = np.abs(df_ - df_.iloc[0,:]) # 每一行指标和要参考的指标做减法,取绝对值。
    global_max = df_.max().max()
    global_min = df_.min().min()
    df_r = (global_min + r*global_max)/(df_ + r*global_max) # 求关联矩阵
    return df_r.mean(axis=1)

# gain增益型
def gain(df,normaliza):
    for i in range(df.shape[0]):
        if normaliza == "initial" or normaliza==None:
            df.iloc[i] = df.iloc[i]/df.iloc[i,0]
        elif normaliza == "mean":
            df.iloc[i] = df.iloc[i]/df.mean(axis=1)
    return df

# cost成本型
def cost(df,normaliza):
    for i in range(df.shape[0]):
        if normaliza == "initial" or normaliza==None:
            df.iloc[i] = df.iloc[i,0]/df.iloc[i]
        elif normaliza == "mean":
            df.iloc[i] = df.mean(axis=1)/df.iloc[i]
    return df

# 自定义级别0-1型
def level_(df,normaliza,level):
    # 把这个表中等于1和等于0的数,重新分成两个表,调用上面两个方法。在合成一张表
    df_gain = df[df[level]==1]
    df_cost = df[df[level]==0]
    df_1 = gain(df_gain,normaliza)
    df_2 = cost(df_cost,normaliza)
    return df_1.append(df_2)


现在有这样一组数据,通过对某健将级女子铅球运动员的跟踪调查,获得其 1982 年至 1986 年每年最好成绩及16 项专项素质和身体素质的时间序列资料,见表,试对此铅球运动员的专项成绩进行因素分析。
这是其他文章中的例子,那篇文章用matlab代码写的。传送门

# 数据如下
x = np.array([
    [13.6,14.01,14.54,15.64,15.69],
    [11.50,13.00,15.15,15.30,15.02],
    [13.76,16.36,16.90,16.56,17.30],
    [12.41,12.70,13.96,14.04,13.46],
    [2.48,2.49,2.56,2.64,2.59],
    [85,85,90,100,105],
    [55,65,75,80,80],
    [65,70,75,85,90],
    [12.80,15.30,16.24,16.40,17.05],
    [15.30,18.40,18.75,17.95,19.30],
    [12.71,14.50,14.66,15.88,15.70],
    [14.78,15.54,16.03,16.87,17.82],
    [7.64,7.56,7.76,7.54,7.70],
    [120,125,130,140,140],
    [80,85,90,90,95],
    [4.2,4.25,4.1,4.06,3.99],
    [13.1,13.42,12.85,12.72,12.56]
])

因为最后两个指标是成本型,前面的都是增益型,所以我们另外加一列表示他的类型

df1 = pd.Dataframe(x)
df1["level"] = np.array([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0])


将这个数据传入方法中,即可得到最终的关联系数
0 1.000000
1 0.588106
2 0.662749
3 0.853618
4 0.776254
5 0.854873
6 0.502235
7 0.659223
8 0.582007
9 0.683125
10 0.695782
11 0.895453
12 0.704684
13 0.933405
14 0.846704
15 0.745373
16 0.726079
第一行是铅球专项成绩x0,本身和自己最关联,这个不用看,剩下关联最强的就是x13全蹲,这样可以做针对性训练。最后还可以排个序。


再讨论一下这个关联系数矩阵,步骤中第五步求出的。
针对上面的,关联矩阵如下,

画一个图,从里面挑几行出来画,要不太多了,看不清楚。

挑的数据为[0,1,2,3,4,13,16]这几行,其中0就是参考的指标。
可以看得出来,x13是关系最强的,所以和0的那条直线挨的最近,1,2,3中3是最强的,所以红色的线也在上面。(调节系数r的大小,画出图的紧凑程度也不一样。这里就不试了。)

这就是一开始说的,若两个因素变化的趋势具有一致性,即同步变化程度较高,即可谓二者关联程度较高;反之,则较低。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5593633.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-15
下一篇 2022-12-15

发表评论

登录后才能评论

评论列表(0条)

保存