2017-05-22 4 views
0

에 대한 루프를 만들기 위해 :어떻게이 같은 예를 들어 위치와 데이터 프레임이 거리 R

id  lat   lon 
a 51.50549 -0.0924609 
b 37.80248 -122.416634 
c 51.50609 -0.1238904 

등등을.

나의 목표는 "a"라는 위치를 선택했을 때 "a"에서 반경 500km에있는 위치 만 포함하고 이보다 더 먼 모든 것을 제외시킬 하위 세트가있을 것입니다. 최종 위치가 각기 다른 위치에 대해 고유 할 수 있도록 선택한 위치가 계속 변경 될 것이므로 루프가되어야한다고 생각합니다.

+0

및 최종 결과는 어떻게 생겼습니까? 당신은 [귀하의 질문을 재현 가능하게 만들어야합니다.] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example#5963610) 'geosphere :: distHaversine' -이 유용합니다. – alistaire

답변

0

지형 라이브러리를 사용할 수 있다고 제안되었습니다. 당신의 데이터는 데이터 테이블입니다 :

library(geosphere) 
library(data.table) 

# asumming your dataframe is named "d" 

d <- data.table(d) 

# CALCULATE DISTANCE (dist) TO EACH ID (dist_to) 

for (i in 1:nrow(d)) { 
     print (d[i,]$id) 
     for (j in 1:nrow(d)) { 

     d1 <- d[id == d[i,]$id, dist:=distm(c(d[i,]$lon, d[i,]$lat), c(d[j,]$lon, d[j,]$lat), fun = distHaversine)/1000, ] 
     d1 <- d1[, dist_to:= d[j,]$id,] 
     if(exists('d2')){ d2<-rbindlist(list(d2,d1))} else {d2<-copy(d1)} 
    } 
} 


head(d) 
    id lat   lon   dist  dist_to 
1: a 51.50549 -0.0924609 0.000000  a 
2: b 37.80248 -122.4166340 8623.657407  a 
3: c 51.50609 -0.1238904 0.000000  a 
4: a 51.50549 -0.0924609 8625.195873  b 
5: b 37.80248 -122.4166340 8623.657407  b 
6: c 51.50609 -0.1238904 0.000000  b 

# SELECT DISTANCES LESS THAN 500kms 

    d[dist <= 500,] 

    id  lat  lon  dist  dist_to 
    1: a 51.50549 -0.0924609 2.178749  c 
    2: c 51.50609 -0.1238904 0.000000  c 

희망이 있습니다.

+0

이봐, 노력했지만 오류가 발생했습니다 : 목록 입력 항목 1이 data.frame, data가 아닙니다.테이블 또는 목록 나는 또한 복사하여 df 빌드를 사용하여 코드를 실행하고 여전히 동일한 오류가 발생했습니다. –

0

당신은 정도의 좌표에서의 거리를 계산하기 위해 sp 패키지를 사용할 수 있습니다 중첩 루프를 사용

library(sp) 

# reproducing your example dataset 
id<-c("a","b","c") 
lat<-c(51.50549,37.80248,51.50609) 
lon<-c(-0.0924609, -122.416634, -0.1238904) 
d<-data.frame(id,lat,lon) 
d 
    id  lat   lon 
1 a 51.50549 -0.0924609 
2 b 37.80248 -122.4166340 
3 c 51.50609 -0.1238904 

# x and y coordinates must be in first two columns 
d2<-as.matrix(d[,-1]) 

# spDistsN1 function from sp package calculates distance 
# specify longlat=TRUE if you use degrees, gives result in km 
s<-nrow(d) 
km2<-lapply(1:s,function(i) d[which(spDistsN1(d2,d2[i,],longlat=TRUE)<=500),]) 

# the result is in a list, each element corresponding to each record 
km2 
[[1]] 
    id  lat  long 
1 a 51.50549 -0.0924609 
3 c 51.50609 -0.1238904 

[[2]] 
    id  lat  long 
2 b 37.80248 -122.4166 

[[3]] 
    id  lat  long 
1 a 51.50549 -0.0924609 
3 c 51.50609 -0.1238904 
0

조금 너무 많이 이럴 것 같다.

나는 raster 패키지에서 기능 만 사용이 선 주위에 뭔가를 제안 할 것입니다 :

#load package 
library(raster) 

# create dataframe 
df <- data.frame(id=c('a','b','c'), lat=c(51.50549,37.80248,51.50609), lon= c(-0.0924609,-122.416634,-0.1238904)) 

를 이제 이러한 위도 및 경도, 나는 지리적으로 투사 문자열을 만드는거야와 지점 위치이기 때문에 좌표계 :

pj <- CRS('+proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0') 

내가 가장 깨끗한 방법은 당신이 (내가 getPoints를 호출) 원하는 정확히 않는 작은 함수를 정의하는 것입니다 생각 :

getPoints <- function(df,id){ 

    refpoint <- SpatialPoints(df[df$id==id,3:2],proj4string=pj) 

    pdist <- pointDistance(refpoint,SpatialPoints(df[,3:2],proj4string=pj),lonlat = T) 

    return(df[pdist < 5000,]) 
} 

포인트 간 거리를 계산하려면 raster 패키지의 pointDistance을 사용하고 있습니다. 전/거리를 계산할 때 좌표를 SpatialPoints 및 정의 된 투영 pj으로 공간 점으로 변환해야합니다. 함수에 id이 제공된 참조 점 refpoint을 선택하고 데이터 프레임 df의 모든 점까지의 거리를 계산합니다. 또한 점 자체에 대한 거리를 계산하므로 pdist <= 500000 조건으로 모든 점을 인덱싱 할 수 있으며 거리가 0이므로 선택한 점도 반환합니다.

줄여서 변수에 refpoint을 할당하는 것을 피할 수 있었지만 조금 더 명확 해졌습니다.

마지막으로 할 수 편리하게 목록에 내 결과를 저장하고 일반적으로 반복되지 않도록됩니다 지점 위치

for (id_sel in df$id){ 

print(getPoints(df,id_sel)) 

} 

또는 lapply 사용을 통해 하나 루프 : 위치는 어떤 기능을 수행

lapply(df$id,function(x) getPoints(df,x))