es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿Es posible filtrar un objeto de función simple (sf) utilizando selectizeGroupUI en R shiny?

Estoy tratando de construir una aplicación de Shiny que contenga un mapa de Leaflet que muestre trayectorias de movimiento, que se puedan filtrar bidireccionalmente usando otras dos columnas en el conjunto de datos que contiene los datos de geometría.

Para hacerlo, estoy tratando de usar selectizeGroupUI (paquete shinyWidgets), que permite filtrado bidireccional/dependiente.

Sin embargo, cuando ejecuto el código, obtengo el siguiente error:

“Advertencia: Error en polygonData.default: No sé cómo obtener datos de ruta de objeto de clase data.frame”

Tengo la sensación de que esto se debe a que el mapeo de datos de trayectoria (linestring) en un mapa de Leaflet requiere que el conjunto de datos subyacente sea un objeto sf, mientras que selectizeGroupUI convierte el objeto sf en un data.table(?), por lo tanto, el mensaje de error.

Esto se admite por el hecho de que cuando convierto el conjunto de datos de objeto sf a data.table y trato de trazar las trayectorias como coordenadas individuales A y B (sin una línea de conexión), todo funciona perfectamente.

¿Alguna idea de si existe una solución alternativa?

¡Cualquier ayuda sería muy apreciada, por favor y gracias!

Un reprex:


biblioteca(tidyverse) biblioteca(sf) biblioteca(brillante) biblioteca(shinyWidgets) generar la tabla con datos de geometría geo-datos <- estructura(lista(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), startlat = c(33.40693,33.64672, 33.57127, 33.42848, 33.54936, 33.53418, 33.60399, 33.49554,33.5056, 33.61696), startlong = c(-112.0298, -111.9255, -112.049 , -112.0998, -112.0912, -112.0911, -111.9273, -111.9687, -112.0563, -111.9866), endlat = c(33.40687, 33.64776, 33.57125, 33.42853,33.54893, 33.53488, 33.60401, 33.49647, 33.5056, 33.61654), endlong = c(-112.0343,-111.9303, -112.0481, -112.0993, -112.0912, -112.0911, -111.931,-111.9711, -112.0541, -111.986)), row.names = c(NA, -10L), spec = estructura(lista(cols = lista(idx = estructura(lista(), clase = c("recolector doble", "colector")), empezarlat = estructura(lista(), clase = c("recolector doble", "recolector")), empezarlong = estructura(lista(), clase = c("recolector doble", "recolector")), endlat = estructura(lista(), clase = c("recolector doble", "recolector")), endlong = estructura(lista(), clase = c("recolector doble", "recolector"))), predeterminado = estructura(lista(), clase = c("recolector adivinar", "colector")), delim = ","), clase = "especificación de columna"), clase = c("data.table","data.frame")) geo-datos<- setDT(geo-datos) geo-datos <- geo-datos[ , { geometría <- sf::stlinestring(x = matrix(c(startlat, startlong, endlong, endlong), ncol = 2, byrow = T)) geometría <- sf::stsfc(geometría) geometry <- sf::st_sf(geometry = geometry) } , por = idx ] generar la tabla con columnas para filtrar los datos de geometría, unirse a los datos de geometría y convertir a sf tabla <- estructura(lista(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), columna1 = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "C"), columna2 = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), row.names = c(NA, -10L), class = c("tbl df","tbl", "data.frame")) %>% leftjoin(x = ., y = geo-datos, by = "idx", keep = FALSE) sf <- sf::stassf(tabla) Brillante ui <- fluidPage( fluidRow( columna( ancho = 10, compensación = 1, tags$h3("Filtrar datos con grupo selectize"), panel( selectizeGroupUI( id = "mis-filtros", params = lista( columna1 = lista(inputId = "columna1", title = "columna1:"), columna2 = lista(inputId = "columna2", title = "columna2:") ) ), estado = "primario" ), leafletOutput(outputId = "mapa") ) ) ) servidor <- función(input, output, sesión) { res_mod <- callModule( module = selectizeGroupServer, id = "mis-filtros", datos = sf, vars = c("columna1", "columna2")) salida$mapa <- renderLeaflet({ leaflet() %>% addPolylines(data = res_mod()) }) } brillanteApp(ui, servidor)
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Parece que el error está ocurriendo porque selectizeGroupUI está convirtiendo el objeto sf en un data.table, lo cual no es compatible con la función addPolylines del paquete leaflet. Una solución alternativa podría ser convertir los datos filtrados nuevamente en un objeto sf antes de trazarlo en el mapa. Puedes hacer esto usando la función as_sf() del paquete sf.

    Aquí está el código modificado con esta solución alternativa:

    biblioteca(tr tidyverse)
    biblioteca(sf)
    biblioteca(brillante)
    biblioteca(shinyWidgets)
    
    # generar la tabla con datos de geometría
    
    geo_data <- estructura(lista(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
                               start_lat = c(33,40693,33,64672, 33,57127, 33,42848, 33,54936, 33,53418, 33,60399, 33,49554,33,5056, 33,61696),
                               start_long = c(-112,0298, -111,9255, -112,049,-112,0998, -112,0912, -112,0911, -111,9273, -111,9687, -112,0563, -111,9866),
                               end_lat = c(33,40687, 33,64776, 33,57125, 33,42853,33,54893, 33,53488, 33,60401, 33,49647, 33,5056, 33,61654),
                               end_long = c(-112,0343,-111,9303, -112,0481, -112,0993, -112,0912, -112,0911, -111,931,-111,9711, -112,0541, -111,986)),
                          row.names = c(NA, -10L), spec = estructura(lista(cols = lista(idx = estructura(lista(), clase = c("collector_double", "collector")),
                                                                                     start_lat = estructura(lista(), clase = c("collector_double", "collector")),
                                                                                     start_long = estructura(lista(), clase = c("collector_double", "collector")),
                                                                                     end_lat = estructura(lista(), clase = c("collector_double", "collector")),
                                                                                     end_long = estructura(lista(), clase = c("collector_double","collector"))),
                                                                         default = estructura(lista(), clase = c("collector_guess","collector")), delim = ","),
                                                                    class = "col_spec"),class = c("data.table","data.frame")))
    
    
    geo_data<- setDT(geo_data)
    
    geo_data <- geo_data[
      , {
        geometry <- sf::st_linestring(x = matrix(c(start_long, start_lat, end_long, end_lat), ncol = 2, byrow = T))
        geometry <- sf::st_sfc(geometry)
        geometry <- sf::st_sf(geometry = geometry)
      }
      , by = idx
    ]
    
    
    
    # generar la tabla con columnas para filtrar los datos de geometría, unir con los datos de geometría y convertir en sf
    
    tabla <- estructura(lista(idx = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
                            columna1 = c("A", "A", "A", "B", "B", "B", "C", "C", "C", "C"),
                            columna2 = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)), row.names = c(NA, -10L),
                       class = c("tbl_df","tbl", "data.frame")) %>%
      left_join(x = ., y = geo_data, by = "idx", keep = FALSE)
    
    
    sf <- sf::st_as_sf(tabla)
    
    
    # Brillante
    
    ui <- fluidPage(
      fluidRow(
        column(
          width = 10, offset = 1,
          tags$h3("Filtrar datos con selectize group"),
          panel(
            selectizeGroupUI(
              id = "mis-filtros",
              params = list(
                columna1 = list(inputId = "columna1", title = "columna1:"),
                columna2 = list(inputId = "columna2", title = "columna2:")
              )
            ), status = "primary"
          ),
          leafletOutput(outputId = "mapa")
        )
      )
    )
    
    servidor <- function(input, output, session) {
    
      res_mod <- callModule(
        module = selectizeGroupServer,
        id = "mis-filtros",
        data = sf,
        vars = c("columna1", "columna2"))
    
    
    
      output$mapa <- renderLeaflet({
        datos_filtrados <- res_mod()
        datos_filtrados_sf <- sf::st_as_sf(datos_filtrados)
        leaflet() %>%
        addPolylines(data = datos_filtrados_sf)
      })
    
    }
    
    
    
    brillanteApp(ui, servidor)
    

Comments are closed.