1

データ フレーム内の各ポイント (x、y) について、そのポイントからデータ フレーム内の同じ「グループ」ラベルを持たない他のすべてのポイントまでのユークリッド距離の合計を計算したいと考えています。これは、私が達成しようとしているもののハッキーな for ループ バージョンです。

# some fake data
d <- data.frame(group=rep(c('a','b','c'),each=3), x=sample(1:9), y=sample(1:9), z=NA)
for (i in 1:nrow(d)) {
  d2 <- subset(d,group!=d$group[i])
  d$z[i] <- sum(sqrt((d$x[i]-d2$x)^2 + (d$y[i]-d2$y)^2))
} 

たとえば、点 a1 の目的の値は、a1 から b1、b2、b3、c1、c2、c3 のそれぞれまでの距離の合計である必要がありますが、距離 a1-a2 または a1-a3 は含まれません。これを達成するためのベクトル化された方法はありますか? 私はそれが明らかな解決策だと確信しています...さまざまな構成を試しましby()apply()が、答えにたどり着けないようです。

4

2 に答える 2

3

これを効率的に解決するための非常に優れた方法があります。すべての距離を事前に計算し、ポイントではなくそれらをサブセット化して、同じ計算を繰り返さないようにします。

dists <- as.matrix(dist(d[2:3]))
d$z <- sapply(seq(d$group), function(i) sum(dists[i, !d$group %in% d$group[i]]))
于 2012-10-01T06:43:46.897 に答える
1

Backlinのソリューションとループのベンチマークの結果(違いを増幅するためにサンプルデータを少し大きくしました):

d <- data.frame(group=rep(letters[1:10],each=100), x=sample(1:1000), y=sample(1:1000), z=NA)
loopMethod <- function(d) {
  for (i in 1:nrow(d)) {
    d2 <- subset(d,group!=d$group[i])
    d$z[i] <- sum(sqrt((d$x[i]-d2$x)^2 + (d$y[i]-d2$y)^2))
  }
}
backlinMethod <- function(d) {
  dists <- as.matrix(dist(d[2:3]))
  d$z <- sapply(seq(d$group), function(i) sum(dists[i, !d$group %in% d$group[i]]))
}
system.time(loopMethod(d))
 user  system elapsed 
1.020   0.004   1.021 
system.time(backlinMethod(d))
 user  system elapsed 
0.472   0.052   0.525 
于 2012-10-01T16:17:53.027 に答える