简体   繁体   中英

Clicking a ggmap in a ShinyApp does not return correct coordinates

If I attach a click event to a ggmap in a ShinyApp, and then click the map, I do not get back the correct coordinate points.

The following app plots a map with some points on it, and attaches a click event to the map. My goal is to have it so when I click the points, their data (lon/lat in this case) should appear in the outputId="coords" verbatimTextOutput.

app.R:

library(shiny);
library(ggmap);

# load data
points <- data.frame(lon=c(-122,-121.9,-121.8,-121.7),lat=c(37.2,37.2,37.2,37.2));
map <- get_map(location = c(lon = mean(points$lon),lat = mean(points$lat)),maptype="roadmap",scale=2, zoom =11)


ui <- fluidPage (
  plotOutput(outputId="mapOut",
             width="100%", height="500px",
             click = "plot_click"
  ),
  verbatimTextOutput(outputId="info"),
  verbatimTextOutput(outputId="coords")

)


server <- function(input,output) {

  output$mapOut <- renderPlot({
     mapPoints <-  ggmap(map) + geom_point(aes(x = lon, y = lat),size=8,colour="black", data=points);;
     mapPoints
  })

  output$info <- renderPrint({
    ptClicked <- nearPoints(points, coordinfo = input$plot_click, threshold = 10, maxpoints = 1, xvar="lon", yvar="lat");
    data.frame(lon=ptClicked$lon,lat=ptClicked$lat);

  })

  output$coords <- renderText({
    paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)
  })
}

shinyApp(server = server, ui = ui)

When I run this app the points are displayed in the correct locations. If I click directly on a point, nearPoints() in output$info <- ... does not correctly identify the point. This is because the returned coordinate clicked is wrong. (As you can see from the "coords" verbatim text output.)

If I click to the RIGHT of the point, thereby making the returned click coordinate "on the point" in a data-sense, then the point is returned.

The problem is similar to getting correct click coords with ggplot map in shiny , except in that case the coordinates were being returned as numbers in [0,1]; in my case, the coordinates look like true coordinates but are a bit wrong.... From that question I also noticed that even after rescaling using lon <- 400*x - 200 and lat <- 200*y - 100 the coordinates were still way off (eg (lon,lat)= (0,0) seems to be mapped to around (8.9,5.4)). So ggplot seems to face the same problem when it is used to map.

Is there a way to make a click of a ggmap/ggplot yield the correct coordinate? This might have something to do with projections.

If not, is there a different way to fix things so that the points can be correctly clicked? (Eg, one workaround might be to somehow capture the "as far as clicking is concerned" (x,y) locations of the points plotted, store them, and use them instead of lon/lat for nearPoints() purposes...).

ggmap() by default uses the coord_map() projection in ggplot2 , which distorts the coordinate. To get the correct clicked coordinate in Shiny, you need to turn it back to Cartesian coordinate. This can be done simply by adding coord_cartesian() . As coord_map() has been stripped, aspect ratio of the output map can be any. So you need to change the width and height in plotOutput() to make the map still a nice map.

Below is the code with the small modification mentioned above. It produces correct click and nice map.

library(shiny);
library(ggmap);

# load data
points <- data.frame(lon=c(-122,-121.9,-121.8,-121.7),lat=c(37.2,37.2,37.2,37.2))
map <- get_map(location = c(lon = mean(points$lon),lat = mean(points$lat)),
               maptype="roadmap",scale=2, zoom =11)


ui <- fluidPage (
    plotOutput(outputId="mapOut",
               ##########################################################
               # force the ratio of the width and height so that the map
               # appears as square
               width=530, height=500,  
               click = "plot_click"
    ),
    verbatimTextOutput(outputId="info"),
    verbatimTextOutput(outputId="coords")

)


server <- function(input,output) {

    output$mapOut <- renderPlot({
        mapPoints <-  ggmap(map, extent = "normal") + 
            geom_point(aes(x = lon, y = lat),size=8,colour="black", data=points)
        #########################################################
        # add coord_cartesian() to strip coord_map() from ggmap()
        mapPoints + coord_cartesian()
    })

    output$info <- renderPrint({
        ptClicked <- nearPoints(points, coordinfo = input$plot_click, 
                                threshold = 10, maxpoints = 1, 
                                xvar="lon", yvar="lat");
        data.frame(lon=ptClicked$lon,lat=ptClicked$lat);

    })

    output$coords <- renderText({
        paste0("x=", input$plot_click$x, "\ny=", input$plot_click$y)
    })
}

shinyApp(server = server, ui = ui)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM