我正在努力使计算一个庞大数据集(600,000条记录)的记录中的不同之处成为可能。
第一项任务是使用、单个记录、和不包括该记录的整体data.frame之间的欧几里德距离来计算该数据之间的差异。
考虑到以下样本:
mydf <- data.frame(var1 = rnorm(5), var2 = rnorm(5), var3 = rnorm(5))
one_row <- mydf[1,]这个问题分两个步骤阐述:
mydf[-1,]的每一行相比,one_row的值不同one_row的行索引。然后,我可以对mydf中的每一行迭代这个过程,从而为每一行找到最相似的行。这将允许我执行聚集聚类和计算统计标准,比如基于距离矩阵的Silhoutte。
更新
一种可能的方法是将one_row复制到同样大小的mydf,并通过对其执行将相似度计算矢量化。
replicated <- [rep(1, 5), 1:ncol(a)]正确答案
杰西·特韦德尔和won782的回答对我的问题都是正确的。
Jesse的积极方面是可以定制距离函数,允许使用混合数据类型。负面的一面是,它不是一个单一的表达式,而是一个函数管道。
won782的积极方面是它是在一个表达式中执行的。消极的方面是,它只对矩阵有效,因此,数值变量。
我选择won782答案是因为他的解决方案可以很容易地扩展为计算轮廓准则的基本组件,而不需要存储不同的矩阵。
发布于 2018-01-20 15:39:59
如果我正确理解了您的问题,您希望对给定的向量执行行方向运算,并计算每一行的欧几里德距离。
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函数来查找最小值的索引。
使用矩阵运算:
sqrt(rowSums((t(t(as.matrix(mydf)) - as.numeric(one_row)))^2))在较大数据集上对两种方法进行基准测试
> 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 由此可见,矩阵运算是一种更快的方法。
发布于 2018-01-20 15:52:49
问题:
您可以在dist上使用mydf,但是对于您的计算机(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()
}然后,calculate_distances函数计算从一行到数据集其余部分的欧几里德距离,然后将参数折叠到具有最小距离的参数的名称和值(不包括自身,因此需要包含dist>0)。
然后将vars组合成一个列(这样可以更容易地传递到像calculate_distances这样的函数,而无需指定列名、var1等)。然后使用mutate和map将函数应用于每一行,然后使用unnest解压缩结果(如果愿意,保留原始数据)。
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祝好运!希望这能有所帮助。
https://stackoverflow.com/questions/48356703
复制相似问题