Spatial nearest neighbor assignment in R

后端 未结 2 1401
清歌不尽
清歌不尽 2021-01-07 03:48

I am working on a study that is trying to assign particulate matter exposure to specific individuals based on their addresses. I have two data sets with longitude and lati

相关标签:
2条回答
  • 2021-01-07 04:08

    Here is, with some example data, how you can use pointDistance:

    library(raster)
    
    #subject level data
    subjectID <- c("A1","A2","A3","A4")
    subxy <- matrix(c(-65, 42, -60, 4.5, -70, 20, -75, 41 ), ncol=2, byrow=TRUE)
    #PM Block Locations 
    blockID <- c("B1","B2","B3","B4","B5")
    blockxy <- matrix(c(-68, 22, -61, 25, -70, 31, -65, 11,-63, 21), ncol=2, byrow=TRUE)
    
    # distance of all subxy to all blockxy points
    d <- pointDistance(subxy, blockxy, lonlat=TRUE)
    
    # get the blockxy record nearest to each subxy record
    r <- apply(d, 1, which.min)
    r
    #[1] 3 4 1 3
    

    So the pairs are:

    p <- data.frame(subject=subjectID, block=blockID[r])
    p
    
    #  subject block
    #1      A1    B3
    #2      A2    B4
    #3      A3    B1
    #4      A4    B3
    

    Illustrate that it works:

    plot(rbind(blockxy, subxy), ylim=c(0,45), xlab='longitude', ylab='latitude')
    points(blockxy, col="red", pch=20, cex=2)
    points(subxy, col="blue", pch=20, cex=2)
    text(subxy, subjectID, pos=1)
    text(blockxy, blockID, pos=1)
    for (i in 1:nrow(subxy)) {
        arrows(subxy[i,1], subxy[i,2], blockxy[r[i],1], blockxy[r[i],2])
    }
    

    0 讨论(0)
  • 2021-01-07 04:19

    If you have a big dataset you might want to use the very efficient nabor package as explained by @user3507085 in this answer. Since the question is closed as off-topic I have copy-pasted the answer below, so it "stays alive" in this thread. I don't know if this is considered bad practice and I'm happy to delete/edit if requested (note the distances given by knn are not the geographical distances, but I guess they could be converted to spherical distances by a simple transformation including arcsin):

    lonlat2xyz=function (lon, lat, r) 
    {
    lon = lon * pi/180
    lat = lat * pi/180
    if (missing(r)) 
        r <- 6378.1
    x <- r * cos(lat) * cos(lon)
    y <- r * cos(lat) * sin(lon)
    z <- r * sin(lat)
    return(cbind(x, y, z))
    }
    
    lon1=runif(100,-180,180);lon2=runif(100,-180,180);lat1=runif(100,-90,90);lat2=runif(100,-90,90)
    
    xyz1=lonlat2xyz(lon1,lat1)
    xyz2=lonlat2xyz(lon2,lat2)
    
    library(nabor)
    
    out=knn(data=xyz1,query = xyz2,k=20)
    
    library(maps)
    
    map()
    points(lon1,lat1,pch=16,col="black")
    points(lon2[1],lat2[1],pch=16,col="red")
    points(lon1[out$nn.idx[1,]],lat1[out$nn.idx[1,]],pch=16,col="blue")
    
    0 讨论(0)
提交回复
热议问题