首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >一个记录与整个data.frame之间的最小差异

一个记录与整个data.frame之间的最小差异
EN

Stack Overflow用户
提问于 2018-01-20 13:29:43
回答 2查看 249关注 0票数 1

我正在努力使计算一个庞大数据集(600,000条记录)的记录中的不同之处成为可能。

第一项任务是使用、单个记录、和不包括该记录的整体data.frame之间的欧几里德距离来计算该数据之间的差异。

考虑到以下样本:

代码语言:javascript
复制
mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5))
one_row <- mydf[1,]

这个问题分两个步骤阐述:

  1. 使用矢量化操作返回长度为4的向量,与mydf[-1,]的每一行相比,one_row的值不同
  2. 从点1的向量中提取更类似于one_row的行索引。

然后,我可以对mydf中的每一行迭代这个过程,从而为每一行找到最相似的行。这将允许我执行聚集聚类和计算统计标准,比如基于距离矩阵的Silhoutte。

更新

一种可能的方法是将one_row复制到同样大小的mydf,并通过对其执行将相似度计算矢量化。

代码语言:javascript
复制
replicated <- [rep(1, 5), 1:ncol(a)]

正确答案

杰西·特韦德尔和won782的回答对我的问题都是正确的。

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

won782的积极方面是它是在一个表达式中执行的。消极的方面是,它只对矩阵有效,因此,数值变量。

我选择won782答案是因为他的解决方案可以很容易地扩展为计算轮廓准则的基本组件,而不需要存储不同的矩阵。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-01-20 15:39:59

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

代码语言:javascript
复制
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

结果是欧氏距离的向量。然后,您可以执行which.min函数来查找最小值的索引。

使用矩阵运算:

代码语言:javascript
复制
sqrt(rowSums((t(t(as.matrix(mydf)) - as.numeric(one_row)))^2))

在较大数据集上对两种方法进行基准测试

代码语言:javascript
复制
> 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 

由此可见,矩阵运算是一种更快的方法。

票数 1
EN

Stack Overflow用户

发布于 2018-01-20 15:52:49

问题:

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

答案:

编写一个函数euc并对第二个参数进行矢量化。

代码语言:javascript
复制
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()
}

然后,calculate_distances函数计算从一行到数据集其余部分的欧几里德距离,然后将参数折叠到具有最小距离的参数的名称和值(不包括自身,因此需要包含dist>0)。

然后将vars组合成一个列(这样可以更容易地传递到像calculate_distances这样的函数,而无需指定列名、var1等)。然后使用mutatemap将函数应用于每一行,然后使用unnest解压缩结果(如果愿意,保留原始数据)。

代码语言:javascript
复制
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

祝好运!希望这能有所帮助。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48356703

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档