实现Gower距离功能

时间:2010-11-28 20:22:48

标签: function r

我有一个带数字的矩阵(大小:28列和47行)。此矩阵有一个额外的行,其中包含列的标题(“ordinal”和“nominal”)。

我想在此矩阵上使用Gower距离函数。 Here说:

第i个和第j个单位之间的最终差异是作为每个变量的不相似度的加权和得出的:

    d(i,j) = sum_k(delta_ijk * d_ijk ) / sum_k( delta_ijk )

特别地,d_ijk表示考虑第k个变量计算的第i个和第j个单元之间的距离。这取决于变量的性质:

  • 因子或字符列是 被视为绝对名义上的 变量和d_ijk = 0 if

    x_ik = x_jk,否则为1;

  • 有序列被视为 分类序数变量和
    值被替换为
    相应的位置指数,r_ik in 要素水平。这些位置
    索引(与...不同) 输出R函数等级为
    以下列方式转变

z_ik =(r_ik - 1)/(max(r_ik) - 1)

这些新值z_ik被视为对的观察    区间缩放变量。

就权重delta_ijk而言:

    如果x_ik = NA或x_jk =,则
  • delta_ijk = 0 NA;
  • 在所有其他情况下delta_ijk = 1。

我知道有一个gower.dist函数,但我必须这样做。 所以,对于“d_ijk”,“delta_ijk”和“z_ik”,我试图创建函数,因为我找不到更好的方法。

我从“delta_ijk”开始,我尝试了这个:

Delta=function(i,j){for (i in 1:28){for (j in 1:47){  
+{if (MyHeader[i,j]=="nominal")
+ result=0
+{else if (MyHeader[i,j]=="ordinal") result=1}}}}
+;result}

但是我收到了错误。所以我卡住了,我不能做其余的事。

P.S。对不起,如果我犯错误,但英语不是我经常使用的语言。

3 个答案:

答案 0 :(得分:3)

你为什么要重新发明轮子billyt? R中有几个函数/软件包可以为您计算,包括R中附带的软件包集群中的daisy()

首先,首先从数据中获取这些“数据类型”标题。如果这确实是一个矩阵,则此标题行中的字符信息将使整个矩阵成为字符矩阵。如果它是一个数据框,那么所有列都可能是因素。您要做的是将每列(数据框的组件)中的数据类型编码为'factor''ordered'

df <- data.frame(A = c("ordinal",1:3), B = c("nominal","A","B","A"),
                 C = c("nominal",1,2,1))

这给出了这一点---请注意,由于额外的信息,所有都存储为因子。

> head(df)
        A       B       C
1 ordinal nominal nominal
2       1       A       1
3       2       B       2
4       3       A       1
> str(df)
'data.frame':   4 obs. of  3 variables:
 $ A: Factor w/ 4 levels "1","2","3","ordinal": 4 1 2 3
 $ B: Factor w/ 3 levels "A","B","nominal": 3 1 2 1
 $ C: Factor w/ 3 levels "1","2","nominal": 3 1 2 1

如果我们摆脱第一行并重新编码为正确的类型,我们可以轻松计算Gower的系数。

> headers <- df[1,]
> df <- df[-1,]
> DF <- transform(df, A = ordered(A), B = factor(B), C = factor(C))
> ## We've previously shown you how to do this (above line) for lots of columns!
> str(DF)
'data.frame':   3 obs. of  3 variables:
 $ A: Ord.factor w/ 3 levels "1"<"2"<"3": 1 2 3
 $ B: Factor w/ 2 levels "A","B": 1 2 1
 $ C: Factor w/ 2 levels "1","2": 1 2 1
> require(cluster)
> daisy(DF)
Dissimilarities :
          2         3
3 0.8333333          
4 0.3333333 0.8333333

Metric :  mixed ;  Types = O, N, N 
Number of objects : 3

这与此数据的gower.dist()相同(尽管格式略有不同(as.matrix(daisy(DF)))相同):

> gower.dist(DF)
          [,1]      [,2]      [,3]
[1,] 0.0000000 0.8333333 0.3333333
[2,] 0.8333333 0.0000000 0.8333333
[3,] 0.3333333 0.8333333 0.0000000

你说你不能这样做吗?你能解释一下为什么不呢?因为你似乎已经做了一些努力来做其他人已经为你编码的事情。这不是作业,不是吗?

答案 1 :(得分:0)

我不确定你的逻辑是做什么的,但是为了你自己的利益,你在那里放了太多“{”。我通常使用{}对来包围consequent-clause:

Delta=function(i,j){for (i in 1:28) {for (j in 1:47){  
       if (MyHeader[i,j]=="nominal") {
         result=0
    # the "{" in the next line before else was sabotaging your efforts
        } else if (MyHeader[i,j]=="ordinal") { result=1} }
      result}
                  }

答案 2 :(得分:0)

感谢Gavin和DWin的帮助。我设法解决了问题并找到了合适的距离矩阵。我在重新编码数据类之后使用了daisy()并且工作正常。

P.S。您在我的其他主题中建议的用于更改列类的解决方案:

DF$nominal <- as.factor(DF$nominal)
DF$ordinal <- as.ordered(DF$ordinal)

没用。它只改变了第一个名义和有序列。

再次感谢您的帮助。