0

我正在尝试累积地址,以便在 R 中的地图上绘制它们。我手动获取地址并将它们输入到 .csv 中以导入 R。.csv 的格式如下:

街道号码 | 街道| 城市| 状态

1150 | FM 1960 西路 | 休斯顿 | 德克萨斯州

701 | 凯勒大道 | 凯勒 | 德克萨斯州

每个标题(街道编号、街道、城市和州)都是一个唯一的列,下面的数据被分成各自的列。

我让 R 从 .csv 中读取信息,并将其转换为与 Google Maps API 一起使用的正确格式。我让 API 生成一个 .xml 文件,其中包含与输入的地址对应的信息。一个最小的工作示例如下:

streetnumber1<-paste(data$streetnumber,sep="")
street1<-gsub(" ","+",data$street)
street2<-paste(street1,sep="")
city1<-paste(data$city,sep="")
state1<-paste(data$state,sep="")

url<-paste("http://maps.googleapis.com/maps/api/geocode/xml?address="
,streetnumber1,"+",street2,",+",city1,",+",state1,"&sensor=false",sep="")

调用url会生成两个 Web 地址,可以将其输入 Web 浏览器以导航到 Google Maps API 提供的 .xml 数据。

我希望 .csv 文件中的所有地址都发生这种情况,而无需声明应该生成多少次 url。我觉得这是一个apply功能的工作,但我不确定如何去做。一旦我自动化了 R 和 API 之间的交互,我想解析获得的 .xml 以便我可以提取我正在寻找的信息。

4

3 回答 3

6

这个ggmap包有一个geocode我强烈推荐使用的功能,而不是在这里重新发明轮子。

编辑:既然您说“多个地址”,您可能更喜欢我的版本,它具有data.frame内置用于批量地理编码的方法和一些稳健性检查,并允许使用 Bing Maps API(每天限制 25K 而不是每天 2.5K谷歌地图)。

于 2013-01-30T14:19:58.867 回答
4

从这个问题中我不清楚你到底想从谷歌那里得到什么。我是纬度和经度。如果是,请尝试屏幕截图后面的代码。编辑:根据 Ari B. Friedman 的评论,修改为包括使用包中的geocode函数的替代(和更简单)方法。ggmap

截屏

# Read in the text from your example
mydf <- read.csv(con <- textConnection(
    "streetnumber|street|city|state
    1150|FM 1960 West Road|Houston|TX
    701|Keller Parkway|Keller|TX"), header = TRUE, sep = "|", check.names = FALSE)

# APPROACH 1 - works but Approach 2 probably better (see below)
# Create a new column for the URL to pass to Google API
mydf$url <- with(mydf, paste("http://maps.googleapis.com/maps/api/geocode/xml?address=",
                             streetnumber,
                             gsub(" ", "+", street),
                             city, "+",
                             state, "+",
                             "&sensor=false",
                             sep = ""))

# Check to see what we have in the data frame
str(mydf)

library(XML)
latlon <- lapply(mydf$url, function(x) { # process each element in the column 'url'
       myxml <- xmlTreeParse(x, useInternal = TRUE) # pass the element (an URL) to the XML function
       # parse the result
       lat = xpathApply(myxml, '/GeocodeResponse/result/geometry/location/lat', xmlValue)[[1]]
       lon = xpathApply(myxml, '/GeocodeResponse/result/geometry/location/lng', xmlValue)[[1]]
       data.frame(lat = lat, lon = lon) # return the latitude and longitude as a data frame
   })

# We end up with a list of data frames, so merge the data frames into one:
library(reshape)
latlon <- merge_all(latlon)

# Then bolt the columns on to your existing data frame
mydf <- cbind(mydf, latlon, stringsAsFactors = FALSE)

# We want the latitude and longitude to numbers, not characters
mydf$lat <- as.numeric(mydf$lat)
mydf$lon <- as.numeric(mydf$lon)

require(ggmap)

# APPROACH 2 - let ggmap do the heavy lifting (and 
# comment out Approach 1 if you use this)

mydf$location <- with(mydf, paste(streetnumber,street, city, state,sep = ", "))

latlon <- geocode(mydf$location)
mydf <- cbind(mydf, latlon, stringsAsFactors = FALSE)

# Now plot.
# Be careful when specifying the zoom argument, because larger values can cause
# points to be dropped by geom_point()
ggmap(get_googlemap(maptype = 'roadmap', zoom = 6, scale = 2), extent = 'panel') +
       geom_point(data = mydf, aes(x = lon, y = lat), fill = "red", colour = "black",
                  size = 3, shape = 21)
于 2013-01-30T13:44:49.923 回答
1

当你使用 google Mpas API 时,最好使用他的 JSON API。XML 它不像 JSON 那样轻量级。

为了连续性,我稍微修改了您的原始代码并使用RJSONIOpackage.json 。

## I read your data
dat <- read.table(text = '
streetnumber | street | city | state
1150 | FM 1960 West Road | Houston | TX
701 | Keller Parkway | Keller | TX',header= T, sep = '|')

library(RJSONIO)
## here the use of json in placee of xml
## the static part of the url request
url.base <- "http://maps.googleapis.com/maps/api/geocode/json?address="

## I create a data.frame with your formatted data
dat2 <- data.frame(
  streetnumber1 = paste(dat$streetnumber,sep=""),
  street2 = paste(gsub(" ","+",dat$street),sep=""),
  city1 = paste(dat$city,sep=""),
  state1 = paste(dat$state,sep=""))

## I use apply here to call it for each row
apply(dat2,1, function(x){
  url<-paste(url.base,x[1],"+",x[2],
             ",+",x[3],",+",x[4],"&sensor=false",sep="")
  res <- fromJSON(url)    ## single statement 
  ## e. to get lat/long
  lat.long <- res$results[[1]]$geometry$bounds$northeast
})

res这里只是一个列表。您可以轻松地对其进行细分和解析。

于 2013-01-30T14:01:14.597 回答