I'm looking to generate a geographic heatmap (using 'ggmap') that overlays some dimension (to start, housing prices) over the lat/lon near a city center. Then I want to create circles of equi-distant spacing (i.e. 10 miles per circle) to get an idea how far out. I would also like my heatmap to go from blue to red for low to high of the dimension. I've been struggling with this for a day and this is as far as I got:


  + stat_density2d(data=positions, mapping=aes(x=lon, y=lat, fill=..level..), geom="polygon", alpha=0.2) 
  + geom_point(shape=1, aes(x = housing.data.NY$Longitude, y = housing.data.NY$Latitude, size=sqrt(distance)), data = positions, alpha = .9, color="black") 
  + scale_size(range=c(3,20)) 
  + labs(x = "Longitude", y = "Latitude", fill = "Housing \n Price Density")
  + ggtitle("Housing Prices by Distance\n New York, December 2014")

The code does the following:

  1. Load the created GoogleMap file as a layer
  2. Create price heat maps
  3. Add concentric circles with radius ~ distance from city center (NEEDS WORK)
  4. Scale the circles (or atleast try to)
  5. Add labeling to make the plot more legible
  6. Add plot title

The code produces the following output:

NY Housing Prices by City, Distance


1 Answer 1


Here is a suggestion. I create the circles with gBuffer and then reproject them into WGS84 for ggmap.

To change the colors of the heat map use scale_fill_gradient().


# get the NY coordinates
nyc <- geocode("New York")

# create spatialPoint object
coordinates(nyc) <- ~ lon + lat
proj4string(nyc) <- CRS("+init=epsg:4326")

# reproject to Google Mercator (meters)
nyc.mrc <- spTransform(nyc, CRS = CRS("+init=epsg:3857"))

# concentric rings (in miles):
dist.miles <-  seq(10, 50, 10)

# create a dataframe with the circle coordinates
circ.df <- do.call(rbind,
                  circ <- gBuffer(nyc.mrc, width = n * 1609.344, quadsegs=20)
                  circ.wgs <- spTransform(circ, CRS=CRS("+init=epsg:4326"))
                  coords <- lapply(circ.wgs@polygons, function(x) {x@Polygons[[1]]@coords})
                  data.frame(x=coords[[1]][,1], y=coords[[1]][,2], distance=n)

# text positions
text.pos <- cbind(aggregate( y ~ distance, data=circ.df, FUN=min), x=nyc$lon, row.names = NULL)

# fake a heatmap
xy <- data.frame(x=runif(100, -74.5, -73.5),y=runif(100, 40.2, 41.2))

# get basemap
ny.map <- get_map("New York", zoom = 8)

# plot
ggmap(ny.map) + 
  stat_density2d(data=xy, mapping=aes(x=x, y=y, fill=..level..), geom="polygon", alpha=0.2) +
  scale_fill_gradient(low = "blue", high = "red") +
  geom_path(data=circ.df, aes(x=x, y=y, group=distance), alpha=0.5) +
  geom_text(data=text.pos, aes(x=x, y=y, label=paste0(distance,"mi")))

enter image description here

  • Awesome - thank you! I will try this out and see how it works.
    – Tony D
    Commented Mar 3, 2015 at 0:56
  • By the way, if I wanted to add radii labels? Thank you
    – Tony D
    Commented Mar 3, 2015 at 13:56
  • I would try to extract the coordinates from circ.df. I added a simple example to get you started. For more see docs.ggplot2.org/current/geom_text.html
    – cengel
    Commented Mar 3, 2015 at 18:04
  • I would just like to add (after following this for my dataset that in the UK -upvoted question and answer) that the cocentric circle distances for me did not completely match up to what the function pointDistance() calculated. To improve this I stipulated SpatialPoints.mrc <-spTransform(SptiallPoints, CRS = CRS("+proj=longlat +init=epsg:32718")) which has produced correct results.
    – QPaps
    Commented Aug 7, 2021 at 9:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.