2016-12-01 14 views
2

私はすでにいくつかの解答を見てきましたが、私の問題には適用できませんでした。参照:個別のdfからの距離の計算方法R

Calculating the distance between points in different data frames

Calculating number of points within a certain radius

find locations within certain lat/lon distance in r

find number of points within a radius in R using lon and lat coordinates

Identify points within specified distance in R

私はDF locstopを持っています。 stopごとにlocまでの距離を見つけたいと思います。

私の場所

loc <- data.frame(station = c('Baker Street','Bank'), 
        lat = c(51.522236,51.5134047), 
        lng = c(-0.157080, -0.08905843), 
        postcode = c('NW1','EC3V') 
       ) 

私は、私はこのような何か希望の最終的な結果として

stop <- data.frame(station = c('Angel','Barbican','Barons Court','Bayswater'), 
        lat = c(51.53253,51.520865,51.490281,51.51224), 
        lng = c(-0.10579,-0.097758,-0.214340,-0.187569), 
        postcode = c('EC1V','EC1A', 'W14', 'W2')) 

を停止します。

df <- data.frame(loc = c('Baker Street','Bank','Baker Street','Bank','Baker Street','Bank','Baker Street','Bank'), 
       stop = c('Angel','Barbican','Barons Court','Bayswater','Angel','Barbican','Barons Court','Bayswater'), 
       dist = c('x','x','x','x','x','x','x','x'), 
       lat = c(51.53253,51.520865,51.490281,51.51224,51.53253,51.520865,51.490281,51.51224), 
       lng = c(-0.10579,-0.097758,-0.214340,-0.187569,-0.10579,-0.097758,-0.214340,-0.187569), 
       postcode = c('EC1V','EC1A', 'W14', 'W2','EC1V','EC1A', 'W14', 'W2') 
       ) 

私のデータセットが比較的大きいをので、私は探していますこの問題を解決するための効率的な方法です。

これを達成するためのアイデアはありますか?

+0

私は質問を正しく読んでいないかもしれませんが、停止データフレーム内の各ポイントとlocデータフレーム内の各ポイントとの距離を調べようとしていますか? – Awhstin

+0

@Awhstinはい、正確に...それぞれの距離が 'stop'から' loc'まで – Davis

+1

偶然、私は[昨日の質問に答えました](http://stackoverflow.com/a/40898595/496488) 'circ'に' loc'を、 'dat'に' stop'を置き換え、各データフレームから保持したい列を確実に持ち歩くことができるようにするために、ここで動作します。 (質問は重複していませんが、回答は似ています) – eipi10

答えて

4

これは、expand.gridmergeクリエイティブ変数の名前の変更を使用します。ちょっと人ですが、操作がベクトル化されているのでかなり効率的です。

library(dplyr) 
df <- expand.grid(station = loc$station, stop = stop$station) %>% 
    merge(loc, by = 'station') %>% 
    rename(loc = station, lat1 = lat, lng1 = lng, station = stop) %>% 
    select(-postcode) %>% 
    merge(stop, by = 'station') %>% 
    rename(stop = station, lat2 = lat, lng2 = lng) 
#   stop   loc  lat1  lng1  lat2  lng2 postcode 
# 1  Angel Baker Street 51.52224 -0.15708000 51.53253 -0.105790  EC1V 
# 2  Angel   Bank 51.51340 -0.08905843 51.53253 -0.105790  EC1V 
# 3  Barbican Baker Street 51.52224 -0.15708000 51.52087 -0.097758  EC1A 
# 4  Barbican   Bank 51.51340 -0.08905843 51.52087 -0.097758  EC1A 
# 5 Barons Court Baker Street 51.52224 -0.15708000 51.49028 -0.214340  W14 
# 6 Barons Court   Bank 51.51340 -0.08905843 51.49028 -0.214340  W14 
# 7 Bayswater Baker Street 51.52224 -0.15708000 51.51224 -0.187569  W2 
# 8 Bayswater   Bank 51.51340 -0.08905843 51.51224 -0.187569  W2 

私たちは、その後、Haversine formulaを使用して距離を計算する(ヤコブに触発さ)geosphere::distHaversine()を使用することができます。

df$dist_meters <- geosphere::distHaversine(select(df, lng1, lat1), 
              select(df, lng2, lat2)) 
df %>% 
    select(stop, loc, dist_meters) 
#   stop   loc dist_meters 
# 1  Angel Baker Street 3732.422 
# 2  Angel   Bank 2423.989 
# 3  Barbican Baker Street 4111.786 
# 4  Barbican   Bank 1026.091 
# 5 Barons Court Baker Street 5328.649 
# 6 Barons Court   Bank 9054.998 
# 7 Bayswater Baker Street 2387.231 
# 8 Bayswater   Bank 6825.897 

、ケースであなたの好奇心どのように半正矢公式作品、

latrad1 <- df$lat1 * pi/180 
latrad2 <- df$lat2 * pi/180 
dlat <- df$dlat * pi/180 
dlng <- df$dlng * pi/180 
a <- sin(dlat/2)^2 + sin(dlng/2)^2 * cos(latrad1) * cos(latrad2) 
dist_rad <- 2 * atan2(sqrt(a), sqrt(1-a)) 
df %>% 
    mutate(dist_meters_byhand = dist_rad * 6378137) %>% 
    select(stop, loc, dist_meters_geosphere = dist_meters, dist_meters_byhand) 
#   stop   loc dist_meters_geosphere dist_meters_byhand 
# 1  Angel Baker Street    3732.422   3732.422 
# 2  Angel   Bank    2423.989   2423.989 
# 3  Barbican Baker Street    4111.786   4111.786 
# 4  Barbican   Bank    1026.091   1026.091 
# 5 Barons Court Baker Street    5328.649   5328.649 
# 6 Barons Court   Bank    9054.998   9054.998 
# 7 Bayswater Baker Street    2387.231   2387.231 
# 8 Bayswater   Bank    6825.897   6825.897 
+0

あなたの答えをありがとう、非常に助けてください。何が近くにあると考えていますか?これは同じ国(つまりイギリス)内のデータポイントで動作するのでしょうか、それともこの大規模な距離に球座標が必要ですか?さらに、あなたの答えでどのような単位が測定されていますか? – Davis

+1

私はジェイコブが示唆したように地圏パッケージを使って結果をメートルに変更しました。 –

0

ない(早くまたはおそらく)など巧妙なベンさん@としてではなく、ここでは別の方法です:

library(geosphere) 

master_df <- data.frame() 

for (i in 1:nrow(loc)){ 
    this_loc <- loc[i, 1] 
    temp_df <- cbind(stop, 
        data.frame(loc = this_loc, 
        dist = distm(as.matrix(stop[, 2:3]), c(loc[i, 2], loc[i, 3])))) 
    master_df <- rbind(master_df, temp_df) 
} 

geosphereパッケージは、デフォルトでhaversineを使用しています。これは、正確さが必要な場合に役立ちます。

+0

ご協力いただきありがとうございます。私はあなたのアプローチを試してみると、私はユニークな距離、すなわちdistを得られないことに気づいた。 「エンジェル」と「ベイカーストリート」はdistと同じです。 「エンジェル」から「銀行」? – Davis

+0

おっと!マイナースナフが修正されました... – Jacob