R/neighbors.R

##' Find the nearest k neighbors
##' 
##' @param dismtrx The matrix of distance, typically generated by dist().
##' @param k The number of nearest neighbors that are chosen.
##' @return A data frame of indice. For each row, the i th cell is its i th nearest neighbor.
##' @export
##' @examples
##' data(usGeoInfo)
##' capital_dist=as.matrix(dist(usCapitals[,4:5]))
##' capital_neighbor_3=nnbr(capital_dist)
##' capital_neighbor_5=nnbr(capital_dist, 5)
##' 
nnbr = function(distmtrx,k=3){
    stopifnot(k < nrow(distmtrx))
    res=apply(distmtrx,1,function(xv){order(xv)[1:(k+1)]})
    res=t(res)[,2:(k+1)]
    if (k>1) colnames(res)=paste('N',1:k,sep='')
    return(res)
}

##' Find the neighbors in a range
##' 
##' @param dismtrx The matrix of distance, typically generated by dist().
##' @param r The range that is used as a threshold to define the neighborhood. The unit is not mile or km, but the unit for longitude and latitude.
##' @return A list of neighbors. In each element(region/area), the neighbors are sorted by the distance from the shortest to longest.
##' @export
##' @examples
##' data(usGeoInfo)
##' capital_dist=as.matrix(dist(usCapitals[,4:5]))
##' capital_neighbor=rnbr(capital_dist)
##' 
rnbr = function(distmtrx,r=1){
    stopifnot(r>0)
    res=list()
    for (i in 1:nrow(distmtrx)){
        nb=rownames(distmtrx)[order(distmtrx[i,])]
        res[[i]]=nb[1:sum(distmtrx[i,]<=r)][-1]
    }
    names(res)=rownames(distmtrx)
    return(res)
}

##' Find all the neighbors with shared border.
##' 
##' @param region Region names.
##' @param x X-coordinates of all the vertexes
##' @param y Y-coordinates of all the vertexes
##' @param corner whether the sharing of only one corner point is also defined as "neighbor".
##' @return A list of neighbors. In each element(region/area), the neighbors are sorted by the length of shared vertexes (from the longest to the shortest).
##' @export
##' @examples
##' data(usGeoInfo)
##' state_nbrs=nbrlist(state$abbr,state$x,state$y)
##' state_nbrs=nbrlist(state$abbr,state$x,state$y,corner=FALSE)
##' 
nbrlist = function(region,x,y,corner=TRUE){
    stopifnot(length(x)==length(region) && length(y)==length(region))
    digitx = max(min(nchar(as.character(x))),5)
    digity = max(min(nchar(as.character(y))),5)
    dat=data.frame(r=region,x=x,y=y,stringsAsFactors=FALSE)
    dat$p=paste(round(dat$x,digitx),round(dat$y,digity))
    dat=dat[!duplicated(dat),]
    censordat=dat[duplicated(dat$p)|duplicated(dat$p,fromLast=TRUE),]
    uniregion=if (is.factor(region)) {levels(region)} else {sort(unique(region))}
    k=length(uniregion)
    res=list()
    for (i in 1:k){
        ins=censordat[censordat$r %in% uniregion[i],]
        out=censordat[! censordat$r %in% uniregion[i],]
        tmp=sort(table(out[out$p %in% ins$p,1]),decreasing=TRUE)
        if (corner) {res[[i]]=names(tmp)} else {res[[i]]=names(tmp[tmp>1])}        
    }
    names(res)=uniregion
    return(res)
}
chxy/cartogram documentation built on May 13, 2019, 7:29 p.m.