2016-06-12 5 views
0

私は学校と海岸線の間の最短距離を見つけようとしています。学校はすべて東と北の形式であり、海岸線は東方と北方の形式でもポイントで構成されています。2つのデータセットでUTMポイント間の最短距離を達成するR

私は、学校の場所とすべての海岸線のポイントを比較する学校のループ内の各学校と別のループを通過するループを持つことでこれを解決しました。私が40000の学校と180000の地図ポイントを持っているので、これは信じられないほど遅く、あなたはRで決してループを使うべきではないことを知っています!

テストデータ::私は一緒に以下を入れてみました

schools <- structure(list(URN = c(100000L, 100008L, 100009L, 100010L, 100011L, 100012L), Easting = c(533498L, 530238L, 524888L, 529912L, 528706L, 528386L), Northing = c(181201L, 182761L, 185067L, 184835L, 186594L, 185209L)), .Names = c("URN", "Easting", "Northing"), row.names = c(NA, 6L), class = "data.frame") 

coastline <- structure(list(Easting = c(219588.203816721, 219623.335092579, 219625.861360502, 219661.118975722, 219664.898582579, 219700.155464073), Northing = c(607325.869617586, 607324.434359255, 607386.276450707, 607384.83630279, 607477.377010103, 607475.937159766)), .Names = c("Easting", "Northing"), row.names = c(NA, 6L), class = "data.frame") 

コード

for (sch in schools$URN){ 

    minimumDistance <- 500000 

    SEasting <- schools %>% filter(URN == sch) %$% Easting 
    SNorthing <- schools %>% filter(URN == sch) %$% Northing 

    mindisance <- coastline %>% mutate(distance = 
      min(sqrt((SEasting - Easting)^2 + 
       (SNorthing - Northing)^2))) %$% distance 

    print(paste(sch, "minDistance = ", mindisance)) 
} 

しかし、私は、各海岸線のポイントの結果を得る:

[1] "100000 minDistance = 529243.315102678" "100000 minDistance = 529243.315102678" 
[3] "100000 minDistance = 529243.315102678" "100000 minDistance = 529243.315102678" 
[5] "100000 minDistance = 529243.315102678" "100000 minDistance = 529243.315102678" 

私がしたいのは

です

私が間違っていることは何ですか?

答えて

1

スイッチmutatesummariseに:

for (sch in schools$URN){ 

    minimumDistance <- 500000 

    SEasting <- schools %>% filter(URN == sch) %$% Easting 
    SNorthing <- schools %>% filter(URN == sch) %$% Northing 

    mindisance <- coastline %>% summarise(distance = 
             min(sqrt((SEasting - Easting)^2 + 
               (SNorthing - Northing)^2))) 
%$% distance 

    print(paste(sch, "minDistance = ", mindisance)) 
} 

[1] "100000 minDistance = 529243.315102678" 
[1] "100008 minDistance = 526056.631790224" 
[1] "100009 minDistance = 521044.965922041" 
[1] "100010 minDistance = 524191.165239584" 
[1] "100011 minDistance = 522059.567618869" 
[1] "100012 minDistance = 522987.402491719" 

summariseは、meansumとして、またはこの場合minに特異値を返すために使用されます。 mutateは、列内の各値をの値に変更してから、列全体を返します。私は、元のコードがprintコマンドで繰り返されていた理由を説明していると思います。完全にあなたをforループを回避するために

できます

distances<-sapply(1:nrow(schools), function(x) 
    with(schools[x,], min(sqrt((coastline$Easting-Easting)^2+ 
          (coastline$Northing-Northing)^2)))) 

paste(schools$URN, "minDistance = ", distances) 

私はこれが速いと思います。のは、大規模なデータセットにそれをテストしてみましょう:

set.seed(400) 
URN<-10000:19999 
Easting1<-sample.int(533498, 10000) 
Northing1<-sample.int(180000, 10000) 
schools<-data.frame(URN, Easting = Easting1, Northing = Northing1) 

Easting2<-sample.int(533498, 10000) 
Northing2<-sample.int(180000, 10000) 
coastline<-data.frame(Easting = Easting2, Northing = Northing2) 

f1<- function() 
    for (sch in schools$URN){ 

    minimumDistance <- 500000 

    SEasting <- schools %>% filter(URN == sch) %$% Easting 
    SNorthing <- schools %>% filter(URN == sch) %$% Northing 

    mindisance <- coastline %>% summarise(distance = 
              min(sqrt((SEasting - Easting)^2+ 
                 (SNorthing- 
              Northing)^2))) %$% distance 
print(paste(sch, "minDistance = ", mindisance)) 
    } 

f2<- function(){ 
    distances<-sapply(1:nrow(schools), function(x) 
with(schools[x,], min(sqrt((coastline$Easting-Easting)^2+ 
         (coastline$Northing-Northing)^2)))) 

paste(schools$URN, "minDistance = ", distances) 
} 

library(microbenchmark) 
microbenchmark(f1(), f2(), times = 10) 
##this takes a while to run 

Unit: seconds 
expr  min  lq  mean median  uq  max neval 
f1() 20.013022 20.387663 20.53804 20.625776 20.735973 20.763166 10 
f2() 2.932491 2.971101 2.99707 3.004892 3.031679 3.044733 10 

sapply()方法がある〜6.8倍高速。

+0

ありがとうございます! – pluke

+0

スピードアップしましたか? 'print()'の作業の1/'nrow()'だけを行う必要があります。 –

+0

かなりのように、行列の点で考えて周りに頭を浮かべて得た – pluke

関連する問題