World map with ggmap

后端 未结 4 1848
無奈伤痛
無奈伤痛 2020-11-29 03:43

I am using ggmap and wish to have a map of the world centered on Australia to which I can easily plot geocoded points. ggmap seems to be a lot easier to use compared to some

相关标签:
4条回答
  • 2020-11-29 04:03

    EDIT: Updated to ggplot2 v 0.9.3

    I tried something similar recenty but with little success. However, there are a number of ways to centre a world map from the map package: see here, here, and here. Using code from the latter, here's an example that centers the world map on longitude 160, plots CRAN mirror locations (coordinates obtained using the geocode() function from the ggmap package) on the world map plotted using ggplot2, and colours New Zealand (using geom_polygon). Centering the map on longitude 160 keep all of Africa on the left of the map, and most of Greenland on the right of the map.

    library(maps)
    library(plyr)
    library(ggplot2)
    library(sp)
    library(ggmap)
    
    # Get some points to plot - CRAN Mirrors
    Mirrors = getCRANmirrors(all = FALSE, local.only = FALSE)
    
    Mirrors$Place = paste(Mirrors$City, ", ", Mirrors$Country, sep = "")    # Be patient
    tmp = geocode(Mirrors$Place)
    Mirrors = cbind(Mirrors, tmp)
    
    ###################################################################################################
    # Recentre worldmap (and Mirrors coordinates) on longitude 160
    ### Code by Claudia Engel  March 19, 2012, www.stanford.edu/~cengel/blog
    
    ### Recenter ####
    center <- 160 # positive values only
    
    # shift coordinates to recenter CRAN Mirrors
    Mirrors$long.recenter <- ifelse(Mirrors$lon < center - 180 , Mirrors$lon + 360, Mirrors$lon)
    
    # shift coordinates to recenter worldmap
    worldmap <- map_data ("world")
    worldmap$long.recenter <- ifelse(worldmap$long < center - 180 , worldmap$long + 360, worldmap$long)
    
    ### Function to regroup split lines and polygons
    # Takes dataframe, column with long and unique group variable, returns df with added column named group.regroup
    RegroupElements <- function(df, longcol, idcol){
      g <- rep(1, length(df[,longcol]))
      if (diff(range(df[,longcol])) > 300) { # check if longitude within group differs more than 300 deg, ie if element was split
        d <- df[,longcol] > mean(range(df[,longcol])) # we use the mean to help us separate the extreme values
        g[!d] <- 1 # some marker for parts that stay in place (we cheat here a little, as we do not take into account concave polygons)
        g[d] <- 2 # parts that are moved
      }
      g <- paste(df[, idcol], g, sep=".") # attach to id to create unique group variable for the dataset
      df$group.regroup <- g
      df
    }
    
    ### Function to close regrouped polygons
    # Takes dataframe, checks if 1st and last longitude value are the same, if not, inserts first as last and reassigns order variable
    ClosePolygons <- function(df, longcol, ordercol){
      if (df[1,longcol] != df[nrow(df),longcol]) {
        tmp <- df[1,]
        df <- rbind(df,tmp)
      }
      o <- c(1: nrow(df)) # rassign the order variable
      df[,ordercol] <- o
      df
    }
    
    # now regroup
    worldmap.rg <- ddply(worldmap, .(group), RegroupElements, "long.recenter", "group")
    
    # close polys
    worldmap.cp <- ddply(worldmap.rg, .(group.regroup), ClosePolygons, "long.recenter", "order") # use the new grouping var
    #############################################################################
    
    # Plot worldmap using data from worldmap.cp
    windows(9.2, 4)
    worldmap = ggplot(aes(x = long.recenter, y = lat), data = worldmap.cp) + 
      geom_polygon(aes(group = group.regroup), fill="#f9f9f9", colour = "grey65") + 
      scale_y_continuous(limits = c(-60, 85)) + 
      coord_equal() +  theme_bw() + 
      theme(legend.position = "none",
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        axis.title.x = element_blank(),
        axis.title.y = element_blank(),
        #axis.text.x = element_blank(),
        axis.text.y = element_blank(),
        axis.ticks = element_blank(), 
        panel.border = element_rect(colour = "black"))
    
    # Plot the CRAN Mirrors
    worldmap = worldmap + geom_point(data = Mirrors, aes(long.recenter, lat),
       colour = "red", pch = 19, size = 3, alpha = .4)
    
    # Colour New Zealand
    # Take care of variable names in worldmap.cp
    head(worldmap.cp)
    worldmap + geom_polygon(data = subset(worldmap.cp, region == "New Zealand", select = c(long.recenter, lat, group.regroup)), 
              aes(x = long.recenter, y = lat, group = group.regroup), fill = "blue")
    

    enter image description here

    0 讨论(0)
  • 2020-11-29 04:11

    Check out ggplot's inbuilt coord_map. This can create maps without requiring a third party set of tiles. Its great for simple maps and can use all of the beauty that is ggplot.

    http://docs.ggplot2.org/current/coord_map.html

    0 讨论(0)
  • 2020-11-29 04:15

    I have managed to build world map based on Google Maps. This is unfortunately slightly distorted, as I believe ggmap/Google Maps imposes restrictions (data length = 409600 pixels, with dimension being a multiple of 792). Nevertheless, the following combination of size, scale and zoom parameters delivers Google world map with ggmap.

    Natrally, you can alter lon to change the point of longitudal focus to Australia, as you wish.

    library(tidyverse)
    
    your_gmaps_API_key <- ""
    
    get_googlemap(center = c(lon = 0, lat = 0)
              , zoom = 1
              , maptype="roadmap"
              , size = c(512,396) 
              , scale = 2
              , color = "bw"
              , key = your_gmaps_API_key) %>% ggmap(.)
    

    Note: points on the map are from my own dataset and not produced by the code above, but the world map is of core importance here.

    0 讨论(0)
  • 2020-11-29 04:20

    I recently got the same error and it boiled down to ggmap not liking latitudes outside $\pm$ 80°.

    However, I had to download my image separately as it was too large for a download (with OSM); this is not your problem, but I record it for future readers.

    Here's how I solved it:

    • separate download of a Mercator projected image via BigMap
    • The latitude needed some care: I got the same errors you show with latitude limits outside $\pm$ 80° when I expected everything should be fine till the 85° OSM covers), but I didn't track them down since I anyways don't need the very high latitudes.
    • 0°/0° center was good for my purpose (I'm in Europe :-)), but you can certainly cut the image whereever it is good for you and wrap it yourself by cbind. Just make sure you know the longitude of your cut.
    • then set the bounding box of your image
    • and assign the appropriate classes

    Here's what I do:

    require ("ggmap")
    library ("png")
    
    zoom <- 2
    map <- readPNG (sprintf ("mapquest-world-%i.png", zoom))
    map <- as.raster(apply(map, 2, rgb))
    
    # cut map to what I really need
    pxymin <- LonLat2XY (-180,73,zoom+8)$Y # zoom + 8 gives pixels in the big map
    pxymax <- LonLat2XY (180,-60,zoom+8)$Y # this may or may not work with google
                                           # zoom values
    map <- map [pxymin : pxymax,]
    
    # set bounding box
    attr(map, "bb") <- data.frame (ll.lat = XY2LonLat (0, pxymax + 1, zoom+8)$lat, 
                                      ll.lon = -180, 
                                      ur.lat = round (XY2LonLat (0, pxymin, zoom+8)$lat), 
                                      ur.lon = 180)
    class(map) <- c("ggmap", "raster")
    
    ggmap (map) + 
      geom_point (data = data.frame (lat = runif (10, min = -60 , max = 73), 
                                     lon = runif (10, min = -180, max = 180)))
    

    result:
    ggplot world map

    Edit: I played a bit around with your google map, but I didn't get the latitudes correct. :-(

    0 讨论(0)
提交回复
热议问题