Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 一条记录和整个数据帧之间的最小不相似性_R_Similarity - Fatal编程技术网

R 一条记录和整个数据帧之间的最小不相似性

R 一条记录和整个数据帧之间的最小不相似性,r,similarity,R,Similarity,我试图使计算大规模数据集(600000条记录)记录中的不相似性成为可能 第一项任务是使用单个记录和整个数据之间的欧氏距离计算相异性。frame排除该记录 考虑到以下示例: mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5)) one_row <- mydf[1,] 正确答案 Jesse Tweedle和won782的答案对我的问题都是正确的 Jesse Tweedle的积极方面是可以定制距离函数,

我试图使计算大规模数据集(600000条记录)记录中的不相似性成为可能

第一项任务是使用单个记录整个数据之间的欧氏距离计算相异性。frame排除该记录

考虑到以下示例:

mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5))
one_row <- mydf[1,]
正确答案 Jesse Tweedle和won782的答案对我的问题都是正确的

Jesse Tweedle的积极方面是可以定制距离函数,允许使用混合数据类型。消极的一面是,它不是一个单一的表达式,而是一个函数管道

won782的优点在于它是在一个表达式中执行的。消极的方面是,它只适用于矩阵,因此是数值变量


我选择won782回答,因为他的解决方案可以很容易地扩展为计算轮廓标准的基本组件,而无需存储相异矩阵

如果我正确理解了您的问题,您希望对给定向量执行行操作,并计算每行的欧几里德距离

mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5))
one_row <- mydf[1,]

result = apply(mydf, 1, function(x) {
  sqrt(sum((x - one_row)^2))
})
result
[1] 0.000000 3.333031 3.737814 1.875482 4.216042
在较大数据集上对两种方法进行基准测试

> mydf <- data.frame(var1 = rnorm(10000), var2 = rnorm(10000), var3 = rnorm(10000))
> one_row <- mydf[1,]
> # Matrix operation method
> system.time({ 
+   sqrt(rowSums((t(t(as.matrix(mydf)) - as.numeric(one_row)))^2))
+   })
   user  system elapsed 
  0.000   0.000   0.001 
> # Apply Method
> system.time({ 
+   apply(mydf, 1, function(x) {
+     sqrt(sum((x - one_row)^2))
+   })
+ })
   user  system elapsed 
  5.186   0.014   5.204 
>mydf一行矩阵运算法
>系统时间({
+sqrt(行和((t(作为矩阵(mydf))-作为数字(一行))^2))
+   })
用户系统运行时间
0.000   0.000   0.001 
>#应用方法
>系统时间({
+应用(mydf,1,函数(x){
+sqrt(总和((x-一行)^2))
+   })
+ })
用户系统运行时间
5.186   0.014   5.204 
显然,矩阵运算是一种更快的方法。

问题: 您可以在
mydf
上使用
dist
,但答案对于您的计算机来说太大(
1e11
-ish元素)。因此,挑战在于计算整个数据集每行x的欧几里德距离。你不想一次又一次地重复整个过程,因为你要重复60万次。但是您可以编写一个矢量化函数来计算欧几里德距离,并使用
tidyverse
东西来简洁地应用它

答复: 编写一个函数
euc
,并在第二个参数上对其进行矢量化

library(tidyverse)
euc <- function(x, y) { 
  sqrt(sum((x - y)^2))
}
euc_ <- Vectorize(euc, vectorize.args = "y")
calculate_distances <- function(row, df) {
  dists <- euc_(row, split(df, 1:nrow(df)))
  # gives you name of row and distance that gives minimum distance.
  dists[dists>0 & dists == min(dists[dists>0])] %>% enframe()
}

是否可以将操作矢量化而不是应用循环?原因是,要为每一行计算最相似的行,将需要一段不可行的时间。它不应用nrow(mydf)矢量化操作,而是执行nrow(mydf)apply循环。矩阵方法肯定更快。唯一的缺点是它不能用于混合数据类型。基本上,通过这一步,我们直接获得与每条记录最近的记录,而不存储整个距离矩阵。此外,作为矢量化操作,我们可以快速计算相似度。此外,作为计算距离的函数,我们可以将其更改为欧几里得以外的度量。
> mydf <- data.frame(var1 = rnorm(10000), var2 = rnorm(10000), var3 = rnorm(10000))
> one_row <- mydf[1,]
> # Matrix operation method
> system.time({ 
+   sqrt(rowSums((t(t(as.matrix(mydf)) - as.numeric(one_row)))^2))
+   })
   user  system elapsed 
  0.000   0.000   0.001 
> # Apply Method
> system.time({ 
+   apply(mydf, 1, function(x) {
+     sqrt(sum((x - one_row)^2))
+   })
+ })
   user  system elapsed 
  5.186   0.014   5.204 
library(tidyverse)
euc <- function(x, y) { 
  sqrt(sum((x - y)^2))
}
euc_ <- Vectorize(euc, vectorize.args = "y")
calculate_distances <- function(row, df) {
  dists <- euc_(row, split(df, 1:nrow(df)))
  # gives you name of row and distance that gives minimum distance.
  dists[dists>0 & dists == min(dists[dists>0])] %>% enframe()
}
mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5))

mydf %>% 
  mutate(n = row_number()) %>% 
  group_by(n) %>% 
  nest(var1, var2, var3) %>% 
  mutate(ans = map(data, calculate_distances, df = mydf)) %>%
  unnest(ans, data)
# A tibble: 5 x 6
      n  name    value         var1       var2       var3
  <int> <chr>    <dbl>        <dbl>      <dbl>      <dbl>
1     1     4 1.027080  0.035684445  0.3152272  1.9001506
2     2     5 1.453509 -0.985996620  0.2650241 -0.2146157
3     3     2 1.645737  0.009665813 -0.8393461  0.4907029
4     4     1 1.027080  0.314943627  0.9910671  1.1789382
5     5     2 1.453509  0.436344415  0.5309611 -0.3521368