【问题标题】:Probability weights for distance matrix in RR中距离矩阵的概率权重
【发布时间】:2020-04-30 07:02:00
【问题描述】:

我正在尝试按照 Anderberg (1973: 124-5) 的建议使用概率权重计算所有名义变量的距离矩阵。 Anderberg (1973: 124) 认为,“赋予稀有类别额外权重的愿望经常出现在生物学文献中,尽管没有提供分配此类权重的系统方法。 [...] 由于罕见事件的概率很低,因此事件的概率不是合适的权重;然而,概率的任何反函数都可能很有趣。'

我将尝试使用 R 中的一个简单而小型的数据集来说明这种情况。

var_1 <- c('A', 'A', 'B', 'A')
var_2 <- c('C', 'C', 'D', 'E')
var_3 <- c('G', 'G', 'G', 'F')
print(test.df <- data.frame(var_1, var_2, var_3))

这会产生以下数据帧

  var_1 var_2 var_3
1     A     C     G
2     A     C     G
3     B     D     G
4     A     E     F

我们可以使用高尔系数计算距离矩阵,如下所示。

library(cluster)
test.dist <- daisy(test.df, metric="gower")
round(test.dist,2)

这会产生以下矩阵。

     1    2    3
2 0.00          
3 0.67 0.67     
4 0.67 0.67 1.00

我们可以看到,例如,观察 1 和 2 对于三个变量是相同的,导致距离为 0。观察 1 和 3 不是;它们在三个变量中的两个(var_1var_2)上有所不同,导致距离为 2/3=0.67。

现在我的问题如下。在数据框中,我们可以看到 var_3 中的值 G 占数据的 75%。我想使用此信息来调整此变量对相似性的贡献。换句话说,因为 var_3 中G 的概率是F 概率的三倍,所以在这个变量中包含F 的两个观测值(行)应该被认为比包含值@987654332 的两个观测值更相似@。

只是为了提供一些背景信息:我的真实数据集中的一些变量具有高度倾斜的分布,其中一个值占该变量所有观察值的 80%,剩下的 20% 分布在其他三个值上。

(我知道我可以使用weights 参数向菊花函数添加权重,但这些权重不依赖于特征值的分布,相反,这些权重对于变量中的所有值都是恒定的.)

【问题讨论】:

  • 您的示例不可重现。您没有提供 test_corpus 并且 R 基函数 dist 没有 metric= 参数或 weights= 参数。你指的是包cluster中的daisy函数吗?
  • 对不起,你是对的。 test_corpus 应该是 test.df。我现在已经改变了。由于weights 参数,我已将dist 函数更改为daisy。我已经测试了代码,现在应该可以重现了。

标签: r matrix distance weighted


【解决方案1】:

安德伯格的建议没有得到实施的原因可能表明了这样做的难度。第一个问题是决定如何设置权重。您将它们基于类别的相对频率,但这会因样本而异,因此您将为不同的样本设置不同的权重。其次,Gower 度量已经在处理多种数据类型,因此您会使其更加复杂,但 Gower 是唯一尝试组合不同数据类型的距离度量。该实现在cluster 包中确实有一个功能,它可能与您想要的足够接近。 Gower 的其他实现可能具有更多功能(搜索 gower distance r 以获取其他实现 gower distance 的包)。在daisy 中有两种处理二进制数据的方法,对称和非对称。不同之处在于 '0-0' 以对称(又名简单匹配系数)计算,但不以非对称(又名 Jaccard)计算。使用非对称接近你想要的,但你必须将因子变量转换为二进制。 daisy 函数实际上对分类变量执行此操作,但它不允许您为非二元变量指定非对称变量。

A <- ifelse(test.df$var_1 == "A", 1, 0)
B <- ifelse(test.df$var_1 == "B", 1, 0)
C <- ifelse(test.df$var_2 == "C", 1, 0)
D <- ifelse(test.df$var_2 == "D", 1, 0)
E <- ifelse(test.df$var_2 == "E", 1, 0)
E <- ifelse(test.df$var_2 == "E", 1, 0)
F <- ifelse(test.df$var_3 == "F", 1, 0)
G <- ifelse(test.df$var_3 == "G", 1, 0)
dta <- cbind(A, B, C, D, E, F, G)

如果您要使用此过程,有一些方法可以自动执行此过程,但这是一个概念验证答案。您的示例数据集太小,无法显示两种方法之间的差异,但如果您在示例数据中增加样本量,您应该会看到差异。

daisy(dta, metric="gower")    # symmetric
daisy(dta, metric="gower", type=list(asymm=1:7))

当然,您始终可以编写自己的 Gower 距离版本并结合自定义加权系统。 R 中提供了一些通用距离函数,可让您编写自己的函数来计算两行之间的距离,并使用它来计算完整的距离矩阵。

【讨论】:

  • 谢谢你,德卡尔森。我确实担心安德伯格的建议没有在任何地方实施。我现在自己编写了这个函数,但正如预期的那样,它非常慢——我认为部分原因是编码效率低下。您之前曾想到将分类变量转换为二进制变量并使用 Jaccard 系数 (asymm) 的建议,但我犯了不检查变量数据类型的错误,因此结果不正确。在你的帮助下,我希望我能做大部分我想做的事。谢谢! PStype=list(assymm=1:7)有错别字(assymm->asymm)
猜你喜欢
  • 2022-01-12
  • 1970-01-01
  • 2016-12-29
  • 1970-01-01
  • 2013-06-20
  • 2013-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多