在R Shiny中删除特定的leaflet标记。

7

我有一个CircleMarkers图层,我想要删除仅具有特定layerId的标记。这些圆形标记的id在数据框中。

以下是一个简单的示例: 假设我有一个包含id为1、2和3的3行数据框。我尝试使用checkboxInput来删除id为1和2或3的选项。

下面的输入将触发ObserveEvent,使用removeMarker函数。然而,什么也没有发生。我已经尝试了无数种方法将id输入removeMarker,并且还尝试了几种其他删除方式。要么什么都不会发生,要么全部消失。我需要一种删除特定标记的方法。

 ui <- shinyUI(fluidPage(
sidebarLayout(
    sidebarPanel(
        checkboxInput("delete1", "Delete ID=1 and 2",value=FALSE),
    checkboxInput("delete3", "Delete ID=3",value=FALSE)
    ),
    mainPanel(
        leafletOutput("map")
    )
)
))

df <- data.frame(id=c(1,2,3),lng = rnorm(3, -106.1039361, 0.5) ,
              lat = rnorm(3, 50.543981, 0.5))

server <- shinyServer(function(input, output, session) {

output$map <- renderLeaflet(
    leaflet() %>% 
addTiles() %>% addCircleMarkers(layerId=df$id,df$lng,df$lat, group='marker', radius=2, fill = TRUE,color='red') 


    )

observeEvent(input$delete1, {
    proxy <- leafletProxy('map')
    if (input$delete1){ proxy %>% removeMarker(df[1:2,1])
 }
 })

observeEvent(input$delete3, {
    proxy <- leafletProxy('map')
    if (input$delete3){ proxy %>% removeMarker(3)}
   })
})

 shinyApp(ui, server)
3个回答

3

出于某些原因,如果在addCirleMarkersremoveMarker中的layerId是字符,则会起作用,您可以尝试在服务器端使用:

server <- shinyServer(function(input, output, session) {

  output$map <- renderLeaflet(
    leaflet() %>% 
      addTiles() %>% addCircleMarkers(layerId=as.character(df$id),df$lng,df$lat, group='marker', radius=2, fill = TRUE,color='red') 


  )

  observeEvent(input$delete1, {
    proxy <- leafletProxy('map')
    if (input$delete1){ proxy %>% removeMarker(c("1","2"))
    }
  })

  observeEvent(input$delete3, {
    proxy <- leafletProxy('map')
    if (input$delete3){ proxy %>% removeMarker("3")}
  })

})

2

我认为对ID进行分组仍然是可行的。那个分组变量可以添加到您的数据框中,您可以使用它来切换显示/隐藏点,就像我下面所示的那样。这与您最初尝试的并没有什么不同,因为您仍然必须明确地标识出要删除的ID。你仍然必须这样做,但现在你必须把它们放在定义好的组里。

require(shiny)
require(leaflet)
require(dplyr)

ui <- shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      #Set value = TRUE so points are shown by default
      checkboxInput("delete1", "Toggle ID 1 and 2", value = TRUE),
      checkboxInput("delete3", "Toggle ID 3", value = TRUE)
    ),
    mainPanel(
      leafletOutput("map")
    )
  )
))


df <- data.frame(
        id = c(1,2,3),
        #Add grouping variable
        group = c("one", "one", "two"),
        lng = rnorm(3, -106.1039361, 0.5) ,
        lat = rnorm(3, 50.543981, 0.5)
)


server <- shinyServer(function(input, output, session) {

  output$map <- renderLeaflet(
    leaflet() %>% 
    addTiles() %>%

    #Add markers with group
    addCircleMarkers(group = df$group, df$lng, df$lat, radius=2, fill = TRUE, color = 'red') 
  )

  observeEvent(input$delete1, {
    proxy <- leafletProxy('map')

    #Always clear the group first on the observed event 
    proxy %>% clearGroup(group = "one")

    #If checked
    if (input$delete1){

      #Filter for the specific group
      df <- filter(df, group == "one")

      #Add the specific group's markers
      proxy %>% addCircleMarkers(group = df$group, df$lng, df$lat, radius=2, fill = TRUE, color = 'red')
    }
  })

  #Repeat for the other groups
  observeEvent(input$delete3, {
    proxy <- leafletProxy('map')
    proxy %>% clearGroup(group = "two")
    if (input$delete3){
      df <- filter(df, group == "two")
      proxy %>% addCircleMarkers(group = df$group, df$lng, df$lat, radius=2, fill = TRUE, color = 'red')
    }
  })
})

shinyApp(ui, server)

另一个可用的想法是使用selectInput而不是checkboxInput,您可以在其中选择多个选项。这将避免为每个组观察事件。如下所示。我设置默认情况下显示所有点,并且如果您选择一个组,则会将其从图中删除。
require(shiny)
require(leaflet)
require(dplyr)

df <- data.frame(
        id = c(1,2,3),
        #Add grouping variable
        group = c("one", "one", "two"),
        lng = rnorm(3, -106.1039361, 0.5) ,
        lat = rnorm(3, 50.543981, 0.5)
)

ui <- shinyUI(fluidPage(
  sidebarLayout(
    sidebarPanel(
      #Set value = TRUE so points are shown by default
      selectInput("toggle", "Toggle Groups", choices = unique(df$group), multiple = TRUE)
    ),
    mainPanel(
      leafletOutput("map")
    )
  )
))

server <- shinyServer(function(input, output, session) {

  output$map <- renderLeaflet(
    leaflet() %>% 
    addTiles() %>%
    addCircleMarkers(df$lng, df$lat, radius=2, fill = TRUE, color = 'red') 
  )

  observe({

    proxy <- leafletProxy('map')

    if(is.null(input$toggle)){
      proxy %>% clearMarkers() %>%
       addCircleMarkers(df$lng, df$lat, radius=2, fill = TRUE, color = 'red') 
    } else {

      #Always clear the shapes on the observed event 
      proxy %>% clearMarkers()

      #Filter for the specific group
      df <- filter(df, !(group %in% input$toggle))

      #Add the specific group's markers
      proxy %>% addCircleMarkers(group = df$group, df$lng, df$lat, radius=2, fill = TRUE, color = 'red')
    }
  })

})

shinyApp(ui, server)

0
你可以尝试以下方法,但是目前的设置方式如果取消复选框,则不会重新放置标记。
server <- shinyServer(function(input, output, session) {

    output$map <- renderLeaflet(
      leaflet() %>% 
      addTiles() %>%

      # Add circle markers in different groups
      addCircleMarkers(layerId=df$id[1:2], df$lng[1:2], df$lat[1:2], group='one', radius=2, fill = TRUE,color='red') %>%
      addCircleMarkers(layerId=df$id[3], df$lng[3], df$lat[3], group='two', radius=2, fill = TRUE,color='red') 
    )

    # Remove group 'one'
    observeEvent(input$delete1, {
      proxy <- leafletProxy('map')
      if (input$delete1){ proxy %>% clearGroup(group = "one")}
    })

    # Remove group 'two'
    observeEvent(input$delete3, {
      proxy <- leafletProxy('map')
      if (input$delete3){ proxy %>% clearGroup(group = "two")}
    })
})

 shinyApp(ui, server)

示例是针对3个ID的,并且为了展示有时候我需要添加/删除分组数据。实际问题涉及约一百万个ID,所以我希望避免将它们放在单独的组中。 - DS501
在你的例子中,即使你没有称之为组,你也将它们分成了组。removeMarker(df[1:2,1]) 将 ID 为 1 和 2 的数据分为一组。如果你通过数据框中的某个变量将它们分组,那么你可以避免很多重复的代码(需要为每个组使用一个新的 observeEvent),使用我在另一个答案中展示的 selectInput 想法。 - Jake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接