首页 文章

在R中进行批量地理编码时,使用'apply'系列中的相应函数

提问于
浏览
1

目标:向R传递一个街道地址向量,并返回一个三向量数据帧,其中第一个向量是街道地址(“Street.Address”),第二个向量是纬度(“Lat”),第三个向量是经度(“Lng”) . 为简单起见,我只使用四个地址;也就是说,向量的长度是4 .

方法:我正在使用Jitender Aswani's code使用Google Maps创建地理编码功能' API. The function works brilliantly, and I'能够找到我选择的任何地址的纬度/经度 . 代码:

getGeoCode <- function(address)
{ 
  #Load library
  library("RJSONIO")

  #Encode URL parameters
  address <- gsub(' ','%20',address)

  #Open connection
  connectStr <- paste('http://maps.google.com/maps/api/geocode/json?sensor=false&address=',address, sep="") 
  con <- url(connectStr)
  data.json <- fromJSON(paste(readLines(con), collapse=""))
  close(con)

  #Flatten the received JSON
  data.json <- unlist(data.json)
  lat <- data.json["results.geometry.location.lat"]
  lng <- data.json["results.geometry.location.lng"]
  gcodes <- c(lat, lng)
  names(gcodes) <- c("Lat", "Lng")
  return (gcodes)
}

geocodes<-getGeoCodes("Palo Alto, California")
geocodes

        Lat            Lng 
"37.4418834" "-122.1430195"

尝试在后续代码中调用该函数时遇到了困难 . 让我们调用原始的一个列对象“data.object” . 当我使用Aswani提供的以下代码时......

data.object <- with(data.object, data.frame(Street.Address, lapply(Street.Address, function(val){getGeoCode(val)})))

...我希望函数返回一个长度为4的三列数据帧,其中column1是街道地址,column2是纬度,column3是经度:

Street.Address                                  Lat            Lng
[1] 3625 1ST AVE S SEATTLE WA 98134           47.571010    -122.334447
[2] 2119 RAINIER AVE S SEATTLE WA 98144       47.584136    -122.302744
[3] 9660 16TH AVE SW SEATTLE WA 98106         47.516180    -122.355138
[4] 8300 RAINIER AVE S SEATTLE WA 98118       47.529750    -122.270010

相反,我得到一个五列数据帧,其中第二列中的值在第一个地址'纬度和第一个地址'经度之间交替,第三列中的值在第二个地址'纬度和第二个地址'之间交替经度,等等:

Street.Address                           column2        column3      column4    column5
[1] 3625 1ST AVE S SEATTLE WA 98134        47.571010      47.584136    47.516180    47.529750
[2] 2119 RAINIER AVE S SEATTLE WA 98144  -122.334447    -122.302744  -122.355138  -122.270010
[3] 9660 16TH AVE SW SEATTLE WA 98106      47.571010      47.584136    47.516180    47.529750
[4] 8300 RAINIER AVE S SEATTLE WA 98118  -122.334447    -122.302744  -122.355138  -122.270010

我尝试使用with(),within(),apply()和lapply()函数的不同组合重写命令,我不能R返回一个简单的三列数据帧 . 我知道我忽视了一些显而易见的事情,但我似乎无法弄明白 .

3 回答

  • 1

    Lapply返回一个列表,sapply是一个用户友好的lapply版本,默认情况下返回一个向量或矩阵 . 您可以使用sapply()然后使用t():

    data.object <- with(data.object, data.frame(Street.Address, t(sapply(Street.Address, function(val){getGeoCode(val)}))))
    
  • 1

    有一篇非常棒的帖子解释了 lapply 系列函数之间的差异 . R Grouping functions: sapply vs. lapply vs. apply. vs. tapply vs. by vs. aggregate . 考虑到你的情况,似乎问题是你希望 lapply 返回数据帧的行但返回它的返回列表 . 您可以使用 sapply 但返回向量而不是行 . 您可以做的最好是使用 sapply 并将矢量转换为所需尺寸的矩阵,或 unlist lapply 并执行相同操作 . 让我们尝试第一个选项 .

    addressmat=matrix(sapply(address, function(val){append(val,as.numeric(getGeoCode(val)))}),4,3, byrow=TRUE) 
    addressmat
    [,1]                                  [,2]         [,3]          
    [1,] "3625 1ST AVE S SEATTLE WA 98134"     "47.5698918" "-122.3360067"
    [2,] "2119 RAINIER AVE S SEATTLE WA 98144" "47.583897"  "-122.30269"  
    [3,] "9660 16TH AVE SW SEATTLE WA 98106"   "47.5159917" "-122.3551272"
    [4,] "8300 RAINIER AVE S SEATTLE WA 98118" "47.5295467" "-122.2699776"
    

    这不会返回colnames,但这很容易解决 .

    colnames(addressmat) <- c("Street.Address","Lat","Lng")
    
  • 1

    另一种选择是 Vectorize

    getGeoCodes <- Vectorize(getGeoCode)
    x <- c(
      "3625 1ST AVE S SEATTLE WA 98134", 
      "2119 RAINIER AVE S SEATTLE WA 98144", 
      "9660 16TH AVE SW SEATTLE WA 98106"
    )
    locations <- getGeoCodes(x) # a matrix
    result <- data.frame(
       StreetAdress=x,
       Lat=as.numeric(locations["Lat",]),
       Lng=as.numeric(locations["Lng",])
    )
    rownames(result) <- NULL
    

相关问题