Finding the latitude and longitude of a list of locations

Locations of all Annual Meetings of the Ecological Society of America

Locations of all Annual Meetings of the Ecological Society of America

In my spare time, I help ESA’s Historical Records Committee out with their website. I thought it would be nice to have a map of all of ESA’s annual meetings on the site. I downloaded the list of ESA Annual Meeting locations from the HRC website and got to work in R.

The biggest hurdle for me was translating the names of locations to latitude and longitude to add points to my ggmap. Luckily, someone else had written some functions that really helped with this.

getDocNodeVal=function(doc, path)
{
   sapply(getNodeSet(doc, path), function(el) xmlValue(el))
}

gGeoCode=function(str)
{
  library(XML)
  u=paste('http://maps.google.com/maps/api/geocode/xml?sensor=false&address=',str)
  doc = xmlTreeParse(u, useInternal=TRUE)
  str=gsub(' ','%20',str)
  lng=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lat")
  lat=getDocNodeVal(doc, "/GeocodeResponse/result/geometry/location/lng")
  c(lat,lng)
}

This code has a tiny error in it that caused me a bit of confusion – latitude is set to longitude and vice versa – but other than that it works great at taking a city name and churning out coordinates. That is, unless you have commas in your string or try to submit a bunch at once.

If the string you submit to gGeoCode has commas in it, it will return list() instead of coordinates.

If you try to use gGeoCode with a whole bunch of cities using a for loop or apply function it will return NULL for some or all cities because you’re asking Google for too many results too quickly (I think). I got around that by using Sys.sleep in a for loop.

getlatlong <- function(locations) { #get lat and long for each location using gGeoCode
    dat <- cbind(lat=numeric(0), long=numeric(0))
    for (i in 1:length(locations)) {
        latlon <- gGeoCode(locations[i])1 #choose only the first location returned.
        dat <- rbind(dat, latlon, deparse.level=0)
        Sys.sleep(.5) #returns null values without this
    }
dat <- data.frame(location=locations, dat)
}

You can get the complete code in the github repo here.

Don’t forget the ecology when you’re doing landscape genetics

Because genetic diversity is influenced by both current and historical processes [88], it may be difficult to infer population processes from genetic patterns in landscapes with a history of disturbance.

Banks SC, Cary GJ, Smith AL, Davies ID, Driscoll D a., Gill a. M, Lindenmayer DB, Peakall R: How does ecological disturbance influence genetic diversity? Trends Ecol. Evol. 2013, doi:10.1016/j.tree.2013.08.005.

Russia and Canada should hang out

Our forests are both going though some tough times.

Kharuk VI, Im ST, Oskorbin P a., Petrov I a., Ranson KJ: Siberian pine decline and mortality in southern siberian mountains. Forest Ecology and Management 2013, 310:312–320.

Pinus contorta distribution map in #rstats

I made a map in R for the first time last week using these guides by Kim Gilbert and Mollie Taylor.

Pinus contorta range map including all subspecies. White areas within the distribution boundary contain no lodgepole. Based on Little 1971.

Pinus contorta range map including all subspecies. White areas within the distribution boundary contain no lodgepole. Based on Little 1971.

As you can see, I wasn’t able to show the holes in the distribution properly. Ideally, they would be actual holes showing the base map. I couldn’t get geom_map to not fill in the holes, so I overfilled them with white.

The code for the map is below and the shapefile I used is from the USGS GECSC Tree Species Distribution Maps for North America.

If anyone’s got a shapefile for just subspecies latifolia or a more recent distribution map, I’d love to use it.

pcontorta <- readShapePoly("pinucont.shp")
colors <- brewer.pal(9, "BuGn") # make pretty color palette

basemap <- get_map(location = c(lon = -120, lat= 50), #build basemap of Western North America
  color = 'color',
  source = 'google',
  maptype = 'terrain',
  zoom = 4)
basemap <- ggmap(basemap)

pcontorta.points <- fortify(pcontorta) 

lodgepole <- geom_map(inherit.aes = FALSE, #make a layer for the lodgepole distribution
  aes(map_id=id),
  data=pcontorta.points,
  map=pcontorta.points,
  fill = colors[9],
  alpha = .5 )

holes <- geom_map(inherit.aes = FALSE, #fill the holes with white
  aes(map_id=id),
  data = pcontorta.points[which(pcontorta.points$hole==TRUE),],
  map=pcontorta.points[which(pcontorta.points$hole==TRUE),],
  fill = "#FFFFFF",
  alpha = 1 )

basemap + lodgepole + holes + #put it all together
xlab("Longitude") + ylab("Latitude") +
ggtitle("Lodgepole Pine distribution") 
 
Tagged ,