【问题标题】:r distance between rowsr 行间距
【发布时间】:2019-09-21 11:06:33
【问题描述】:

我很抱歉,这是我在经历了一次灾难性的尝试之后试图挽回自己的一次尝试。现在我有点清楚了。所以我又来了。

我的目标是找到相似的行。所以首先我有兴趣计算行之间的距离。这是下面的测试数据集。

 Row            Blood   x1    x2    x3    x4
 1              A       0.01  0.16  0.31  0.46
 2              A       0.02  0.17  0.32  0.47
 3              A       0.03  0.18  0.33  0.48

 4              B       0.05  0.20  0.35  0.49
 5              B       0.06  0.21  0.36  0.50
 6              B       0.07  0.22  0.37  0.51

 7              AB      0.09  0.24  0.39  0.52
 8              AB      0.1   0.25  0.4   0.53
 9              AB      0.11  0.26  0.41  0.54

 10             O       0.13  0.28  0.43  0.55
 11             O       0.14  0.29  0.44  0.56
 12             O       0.15  0.3   0.45  0.57

这里有两件事 1) 距离 2) 行

考虑这个行组合。

对于 Row(1-4-7-10) ,距离 D = (d1,4 + d1,7 + d1,10 + d4,7 + d4,10 + d7,10)/6

{ Row1-Blood A, Row1-Blood B, Row1- Blood AB, Row1- Blood O } 

Row{1,4,7,10} 之间的距离是基于此概念计算的

d1,4  = Distance between : Row1-Blood A, Row1-Blood B  
d1,7  = Distance between : Row1-Blood A, Row1-Blood AB  
d1,10 = Distance between : Row1-Blood A, Row1-Blood O       
d4,7  = Distance between : Row1-Blood B, Row1-Blood AB  
d4,10 = Distance between : Row1-Blood B, Row1-Blood O     
d7,10 = Distance between : Row1-Blood AB, Row1-Blood O     

d-1-4   = (0.01-0.05)^2 + (0.16-0.20)^2 + (0.31-0.35)^2 +  (0.46-0.49)^2             
d-1-7   = (0.01-0.09)^2 + (0.16-0.24)^2 + (0.31-0.39)^2 +  (0.46-0.52)^2             
d-1-10  = (0.01-0.13)^2 + (0.16-0.28)^2 + (0.31-0.43)^2 +  (0.46-0.55)^2             
d-4-7   = (0.05-0.09)^2 + (0.20-0.24)^2 + (0.35-0.39)^2 +  (0.49-0.52)^2   
d-4-10  = (0.05-0.13)^2 + (0.20-0.28)^2 + (0.35-0.43)^2 +  (0.49-0.55)^2     
d-7-10  = (0.09-0.13)^2 + (0.24-0.30)^2 + (0.39-0.43)^2 +  (0.52-0.55)^2  

同样,我对计算 81 个不同行组合 (3*3*3*3) 之间的距离感兴趣。

最终的预期数据集应如下所示。

 Row         Distance
 1-4-7-10
 1-4-7-11     
 1-4-7-12

 1-4-8-10          
 1-4-8-11          
 1-4-8-12

 1-4-9-10                    
 1-4-9-11                    
 1-4-9-12

 1-5-7-10
 1-5-7-11     
 1-5-7-12

 1-5-8-10          
 1-5-8-11          
 1-5-8-12

 1-5-9-10                    
 1-5-9-11                    
 1-5-9-12  

 1-6-7-10
 .
 .
 .
 3-6-9-12

我知道我可以使用 4 个嵌套循环和列表来做到这一点。我想知道是否有更有效的方法来实现这一点。

【问题讨论】:

  • ?dist 适用于每个组合的整个矩阵 - 例如 dist(dat[-(1:2)]),这可能是一个很好的起点。
  • 这听起来在结构上类似于 k-means 方法,在该方法中,您可以通过与公共质心的最小距离来识别集群。
  • @thelatemail,这是正确的。我可以使用 dist 函数来计算距离,而不是当前的 (x1-y1) + (x2-y2) + (x3-y3) 方法。
  • 我认为您的一些手动计算是错误的。第 4-7 行和第 4-10 行似乎在重复。
  • @thelatemail,你说得对。我现在已经解决了这个问题。谢谢迟到的邮件。

标签: r distance k-means similarity euclidean-distance


【解决方案1】:

“我的目标是找到相似的行。”

两种可能的方法:

1) k-means,将所有数据分成k不同的簇,识别以找到到每个簇的质心的最小距离。

blood_fake$cluster_assignment <- kmeans(blood_fake[, -c(1:2)], centers = 10)$cluster

library(ggplot2)  
ggplot(blood_fake, aes(x1, x2, color = as.factor(cluster_assignment))) + 
  geom_point(size = 0.3) + 
  theme_minimal() + 
  theme(legend.position = "bottom")

2) fuzzyjoin::distance_left_join 可用于查找距离阈值内的匹配项。如果我在子集上单独运行,那么在具有 4 GB RAM 的旧计算机上运行 10,000 行对我来说还可以,但是当我一次尝试全部运行时就冻结了。

library(tidyverse); library(fuzzyjoin)
blood_fake %>%
  filter(type == "A") %>%
  distance_left_join(blood_fake,  by = c("x1", "x2", "x3", "x4"), distance_col = "dist", max_dist = 0.05) %>%
  filter(dist > 0) %>%
  arrange(dist)

#   row.x type.x        x1.x        x2.x        x3.x        x4.x row.y type.y       x1.y        x2.y        x3.y        x4.y        dist
#1   8362      A 0.055618062 0.008783874 0.001162073 0.145280936  4786      B 0.05807814 0.009353543 0.002046247 0.146829206 0.003091180
#2   4284      A 0.163417186 0.032845642 0.114224202 0.339505310  2060     AB 0.16676132 0.031621044 0.115635984 0.339447690 0.003831363
#3   8338      A 0.194389332 0.070951537 0.132582667 0.004634504  4839     AB 0.19793256 0.067944898 0.130012004 0.005525959 0.005384918
#4   6849      A 0.277700944 0.027618307 0.034390833 0.158798952  7698      A 0.27344845 0.025502562 0.033016888 0.160972663 0.005401185
#5   7698      A 0.273448453 0.025502562 0.033016888 0.160972663  6849      A 0.27770094 0.027618307 0.034390833 0.158798952 0.005401185
#6   4281      A 0.281189896 0.323468620 0.107589336 0.096526579  6251      A 0.27891482 0.321343667 0.109619143 0.100667052 0.005563725

测试数据

n <- 10000
set.seed(42)
blood_fake <- data.frame(row = 1:n,
                         type = sample(c("A","B","AB","O"), n, replace = T),
                         x1 = runif(n, min = 0, max = 0.5),
                         x2 = runif(n, min = 0, max = 0.5),
                         x3 = runif(n, min = 0, max = 0.5),
                         x4 = runif(n, min = 0, max = 0.5)
                         )

【讨论】:

  • 感谢乔恩。我知道这做了类似的事情,但不完全是我想要做的。我将进一步探索。
【解决方案2】:

与其他解决方案类似,但我认为您可以在应用于每个组合的函数内进行一些矩阵索引,以选择要加起来的正确单元格:

请注意,默认的?dist 计算是:

sqrt(sum((x_i - y_i)^2))

...当您使用时:

sum((x_i - y_i)^2)

...所以我将下面的结果平方:

dd <- as.matrix(dist(dat[-(1:2)]))^2

apply(
  expand.grid(split(dat$Row, dat$Blood)),
  1,
  function(x) sum(dd[t(combn(x,2))])
)
#  [1] 0.1140 0.0972 0.0828 0.1212 0.1036 0.0884 0.1308 ...

检查与手动计算的第一个期望结果:

L <- c(
d1_4   = (0.01-0.05)^2 + (0.16-0.20)^2 + (0.31-0.35)^2 +  (0.46-0.49)^2,           
d1_7   = (0.01-0.09)^2 + (0.16-0.24)^2 + (0.31-0.39)^2 +  (0.46-0.52)^2,             
d1_10  = (0.01-0.13)^2 + (0.16-0.28)^2 + (0.31-0.43)^2 +  (0.46-0.55)^2,             
d4_7   = (0.05-0.09)^2 + (0.20-0.24)^2 + (0.35-0.39)^2 +  (0.49-0.52)^2,   
d4_10  = (0.05-0.13)^2 + (0.20-0.28)^2 + (0.35-0.43)^2 +  (0.49-0.55)^2,     
d7_10  = (0.09-0.13)^2 + (0.24-0.28)^2 + (0.39-0.43)^2 +  (0.52-0.55)^2
)
sum(L)
# 0.114

【讨论】:

  • 感谢latemail 这个解决方案适用于一个小数据集。但是,当我在更大的数据集上尝试此操作时,我收到一个错误Error: cannot allocate vector of size 680603.5 Gb,该数据集大约有 863 例血型 A、8676 例血型 AB、7951 例血型 B 和 6984 例血型 O。会有是一种替代解决方案,可以扩展到更大的数据集,每组有几千个案例??
  • @EmilyFassbender - 我并不感到惊讶。你打算如何处理 415,000,000,000,000 次比较?
  • 好问题latemail只“保留”距离小于或等于固定阈值的行,比如0.1dist &lt;=0.1
  • @EmilyFassbender - 即使使用非常高效的代码,您也需要等待数小时甚至数天才能使用简单的方法运行这么多计算。整个问题需要重新概念化为更有效的东西,我不确定如何真正做到这一点。
  • 事实上,as.matrix(dist... 函数运行良好,没有任何问题。正是转换结果以匹配行组合apply( expand.grid( 的部分导致了这个问题。知道哪个行组合导致哪个结果在这里非常重要,因为没有它我不知道距离度量指向哪些行。
猜你喜欢
  • 2015-11-20
  • 1970-01-01
  • 2015-10-07
  • 2016-12-29
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-11-08
相关资源
最近更新 更多