R, Shiny and maps: How to render a map according to the choice in the dropdown_menu?

Asked

Viewed 436 times

0

I am working on a Shiny app and would like the map to be rendered according to the user’s choice in a dropdown. I have three maps (M1, m2 and m3), what I need to put on the ui and server?

Follows a reproducible excerpt:

    ## Options ##
options("scipen"=20)

## Pacotes ##
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(plotly)
library(ggplot2)
library(openxlsx)
library(sf)
library(tmap)
library(dplyr)
library(leaflet)
library(BETS)

## Maps ##

# States
map<-st_read("./Brasil/UFEBRASIL.shp", stringsAsFactors = FALSE)

IST<-BETSget(
  c(15925, 15926, 15927, 15928, 15929,
    15930, 15931, 15932, 15933, 15934,
    15935, 15936, 15937, 15938, 15939,
    15940, 15941, 15942, 15943, 15944,
    15945, 15946, 15947, 15948, 15949,
    15950, 15951),
  data.frame = TRUE)

IST1<-BETSget(
  c(15861, 15862, 15863, 15864, 15865,
    15866, 15867, 15868, 15869, 15870,
    15871, 15872, 15873, 15874, 15875,
    15876, 15877, 15878, 15879, 15880,
    15881, 15882, 15883, 15884, 15885,
    15886, 15887),
  data.frame = TRUE)

IST2<-BETSget(
  c(15893, 15894, 15895, 15896, 15897,
    15898, 15899, 15900, 15901, 15902,
    15903, 15904, 15905, 15906, 15907,
    15908, 15909, 15910, 15911, 15912,
    15913, 15914, 15915, 15916, 15917,
    15918, 15919),
  data.frame = TRUE)

names(IST)<-States
names(IST1)<-States
names(IST2)<-States

IST<-lapply(IST, tail, 1)
INST1<-lapply(IST1, tail, 1)
IST2<-lapply(IST2, tail, 1)


Estados<-c("ACRE",
           "ALAGOAS",
           "AMAPÁ",
           "AMAZONAS",
           "BAHIA",
           "CEARÁ",
           "DISTRITO FEDERAL",
           "ESPIRITO SANTO",
           "GOIÁS",
           "MARANHÃO",
           "MATO GROSSO",
           "MATO GROSSO DO SUL",
           "MINAS GERAIS",
           "PARÁ",
           "PARAÍBA",
           "PARANÁ",
           "PERNAMBUCO",
           "PIAUÍ",
           "RIO DE JANEIRO",
           "RIO GRANDE DO NORTE",
           "RIO GRANDE DO SUL",
           "RONDÔNIA",
           "RORAIMA",
           "SANTA CATARINA",
           "SÃO PAULO",
           "SERGIPE",
           "TOCANTINS"
)

IST<-data.frame(States = States,
                I = c(IST$`ACRE`$value,
                      IST$`ALAGOAS`$value,
                      IST$`AMAPÁ`$value,
                      IST$`AMAZONAS`$value,
                      IST$`BAHIA`$value,
                      IST$`CEARÁ`$value,
                      IST$`DISTRITO FEDERAL`$value,
                      IST$`ESPIRITO SANTO`$value,
                      IST$`GOIÁS`$value,
                      IST$`MARANHÃO`$value,
                      IST$`MATO GROSSO`$value,
                      IST$`MATO GROSSO DO SUL`$value,
                      IST$`MINAS GERAIS`$value,
                      IST$`PARÁ`$value,
                      IST$`PARAÍBA`$value,
                      IST$`PARANÁ`$value,
                      IST$`PERNAMBUCO`$value,
                      IST$`PIAUÍ`$value,
                      IST$`RIO DE JANEIRO`$value,
                      IST$`RIO GRANDE DO NORTE`$value,
                      IST$`RIO GRANDE DO SUL`$value,
                      IST$`RONDÔNIA`$value,
                      IST$`RORAIMA`$value,
                      IST$`SANTA CATARINA`$value,
                      IST$`SÃO PAULO`$value,
                      IST$`SERGIPE`$value,
                      IST$`TOCANTINS`$value)
)

IST1<-data.frame(States = States,
                 I = c(IST1$`ACRE`$value,
                       IST1$`ALAGOAS`$value,
                       IST1$`AMAPÁ`$value,
                       IST1$`AMAZONAS`$value,
                       IST1$`BAHIA`$value,
                       IST1$`CEARÁ`$value,
                       IST1$`DISTRITO FEDERAL`$value,
                       IST1$`ESPIRITO SANTO`$value,
                       IST1$`GOIÁS`$value,
                       IST1$`MARANHÃO`$value,
                       IST1$`MATO GROSSO`$value,
                       IST1$`MATO GROSSO DO SUL`$value,
                       IST1$`MINAS GERAIS`$value,
                       IST1$`PARÁ`$value,
                       IST1$`PARAÍBA`$value,
                       IST1$`PARANÁ`$value,
                       IST1$`PERNAMBUCO`$value,
                       IST1$`PIAUÍ`$value,
                       IST1$`RIO DE JANEIRO`$value,
                       IST1$`RIO GRANDE DO NORTE`$value,
                       IST1$`RIO GRANDE DO SUL`$value,
                       IST1$`RONDÔNIA`$value,
                       IST1$`RORAIMA`$value,
                       IST1$`SANTA CATARINA`$value,
                       IST1$`SÃO PAULO`$value,
                       IST1$`SERGIPE`$value,
                       IST1$`TOCANTINS`$value)
)

IST2<-data.frame(States = States,
                 I = c(IST2$`ACRE`$value,
                       IST2$`ALAGOAS`$value,
                       IST2$`AMAPÁ`$value,
                       IST2$`AMAZONAS`$value,
                       IST2$`BAHIA`$value,
                       IST2$`CEARÁ`$value,
                       IST2$`DISTRITO FEDERAL`$value,
                       IST2$`ESPIRITO SANTO`$value,
                       IST2$`GOIÁS`$value,
                       IST2$`MARANHÃO`$value,
                       IST2$`MATO GROSSO`$value,
                       IST2$`MATO GROSSO DO SUL`$value,
                       IST2$`MINAS GERAIS`$value,
                       IST2$`PARÁ`$value,
                       IST2$`PARAÍBA`$value,
                       IST2$`PARANÁ`$value,
                       IST2$`PERNAMBUCO`$value,
                       IST2$`PIAUÍ`$value,
                       IST2$`RIO DE JANEIRO`$value,
                       IST2$`RIO GRANDE DO NORTE`$value,
                       IST2$`RIO GRANDE DO SUL`$value,
                       IST2$`RONDÔNIA`$value,
                       IST2$`RORAIMA`$value,
                       IST2$`SANTA CATARINA`$value,
                       IST2$`SÃO PAULO`$value,
                       IST2$`SERGIPE`$value,
                       IST2$`TOCANTINS`$value)
)

Boxm1<-
  boxPlus(
    title = tags$b("States", style = 'font-family: "Georgia"'),
    closable = FALSE, 
    width = 6,
    status = "danger", 
    solidHeader = TRUE, 
    collapsible = TRUE,
    enable_dropdown = TRUE,
    dropdown_menu = dropdownItemList(), # What should i do here?
    leafletOutput("m1"), # What should i do here?
    footer = NULL
  )

## User Interface ##

header <- dashboardHeaderPlus(title = "MONITOR",
                              titleWidth = 200
)

sidebar <- dashboardSidebar(
  width = 150,
  sidebarMenu(
    menuItem("Maps", tabName = "maps", icon = icon("globe-americas", lib = "font-awesome"))
  )
)

body <- dashboardBody(
  tabItems(
    # Maps
    tabItem(tabName = "maps",
            fluidRow(
              Boxm1 # Maps
            )
    )
  )
)

ui <- dashboardPagePlus(header, sidebar, body)

server <- function(input, output) {

  output$m1<-renderLeaflet({
    tmap_mode("view")
    IST<-inner_join(map, IST, by = c("NM_ESTADO" = "States"))
    IST<-IST[, c(3,1,2,4,5,6)]
    m1<-tm_shape(IST, name = "Maps") +
      tm_polygons("I", palette = "Reds", title = "")
    tmap_leaflet(m1)
  })

  output$m2<-renderLeaflet({
    tmap_mode("view")
    IST1<-inner_join(map, IST1, by = c("NM_ESTADO" = "States"))
    IST1<-IST1[, c(3,1,2,4,5,6)]
    m2<-tm_shape(IST1, name = "Maps") +
      tm_polygons("I", palette = "Reds", title = "")
    tmap_leaflet(m2)
  })

  output$m3<-renderLeaflet({
    tmap_mode("view")
    IST2<-inner_join(map, IST2, by = c("NM_ESTADO" = "States"))
    IST2<-IST2[, c(3,1,2,4,5,6)]
    m3<-tm_shape(IST2, name = "Maps") +
      tm_polygons("I", palette = "Reds", title = "")
    tmap_leaflet(m3)
  })

}


## App ##
shinyApp(ui, server)
  • 1

    just put the leafletOutput() within the body. You have to wear the same ids that were used in the server.

  • 1

    Welcome to Sopt! Here are some tips on how to improve your question here

1 answer

1

INTRODUCTION

Initially I would like to point out that by the code of your app and the problems that existed in it I believe that you are probably starting to use the Shiny. I will then present the solution to your problem and then comment on the mistakes you made in the design of your Shiny application.

In case who is reading did not want to copy and paste code, all the source code including the data are in this repository github.

SOLUTION

To make your app work I had to do several things:

  1. separate data preparation from the app itself;
  2. store the pre-processed data in a data folder;
  3. change your interface;

Changing its directory structure to include the data and separate the preparation of the app itself was thus:

├── app.R
├── Brasil
│   ├── UFEBRASIL.dbf
│   ├── UFEBRASIL.prj
│   ├── UFEBRASIL.sbn
│   ├── UFEBRASIL.sbx
│   ├── UFEBRASIL.shp
│   └── UFEBRASIL.shx
├── data
│   ├── IST1.rda
│   ├── IST2.rda
│   ├── IST.rda
│   └── map.rda
├── preparation.R
└── shiny-maps.Rproj

Here it is important to note that there are two files in R: the preparation.R and the app.R. But why separate? Here it is important to note that often, when we are doing an analysis on our machine, we work on the console iteratively, including the use of functions that take several minutes to complete. In an app Shiny your user does not need and does not going wait several minutes to see the information he wants. That’s why is super important that the most computationally expensive parts of your app are already pre-processed and then you only upload the ready-to-use data into your app. In this specific case, in the file preparation.R the data files are created IST1.rda, IST2.rda and IST.rda, saved in folder data.

The codes from the archive app.R were thus:

## Options ##
options("scipen"=20)

## Pacotes ##
library(shiny)
library(shinydashboard)
library(shinydashboardPlus)
library(shinyWidgets)
library(tmap)
library(dplyr)
library(leaflet)

## Loadind data ##
load(file = 'data/map.rda')
load(file = 'data/IST.rda')
load(file = 'data/IST1.rda')
load(file = 'data/IST2.rda')

## User Interface ##
## Cabeçalho
header <- dashboardHeaderPlus(title = "MONITOR",
                              titleWidth = 200
)

## Barra lateral
sidebar <- dashboardSidebar(
  width = 150,
  sidebarMenu(
    menuItem("Mapa1", tabName = "mapa1"),
    menuItem("Mapa2", tabName = "mapa2"),
    menuItem("Mapa2", tabName = "mapa3")
  )
)

## Caixa 1 para o mapa 1
Boxm1 <-
  boxPlus(
    title = tags$b("States", style = 'font-family: "Georgia"'),
    closable = FALSE, 
    width = 6,
    status = "danger", 
    solidHeader = TRUE, 
    collapsible = TRUE,
    enable_dropdown = TRUE,
    leafletOutput("m1"), # What should i do here?
    footer = NULL
  )

## Caixa 2 para o mapa 2
Boxm2 <-
  boxPlus(
    title = tags$b("States", style = 'font-family: "Georgia"'),
    closable = FALSE, 
    width = 6,
    status = "danger", 
    solidHeader = TRUE, 
    collapsible = TRUE,
    enable_dropdown = TRUE,
    leafletOutput("m2"), # What should i do here?
    footer = NULL
  )

## Caixa 3 para o mapa 3
Boxm3 <-
  boxPlus(
    title = tags$b("States", style = 'font-family: "Georgia"'),
    closable = FALSE, 
    width = 6,
    status = "danger", 
    solidHeader = TRUE, 
    collapsible = TRUE,
    enable_dropdown = TRUE,
    leafletOutput("m3"), # What should i do here?
    footer = NULL
  )

## Body do dashboard
body <- dashboardBody(
  tabItems(
    # Maps
    tabItem(tabName = "mapa1",
            fluidRow(
              Boxm1 # Maps
            )
    ),
    tabItem(tabName = "mapa2",
            fluidRow(
              Boxm2 # Maps
            )
    ),
    tabItem(tabName = "mapa3",
            fluidRow(
              Boxm3 # Maps
            )
    )
  )
)

ui <- dashboardPagePlus(header, sidebar, body)

## Server ##
server <- function(input, output) {

  output$m1 <- renderLeaflet({
    tmap_mode("view")
    IST <- inner_join(map, IST, by = c("NM_ESTADO" = "State"))
    IST <- IST[, c('NM_ESTADO', 'value', 'geometry')]
    m1  <- tm_shape(IST, name = "Maps") +
      tm_polygons(col = "value", palette = "Reds", title = "")
    tmap_leaflet(m1)
  })

  output$m2 <- renderLeaflet({
    tmap_mode("view")
    IST1 <- inner_join(map, IST1, by = c("NM_ESTADO" = "State"))
    IST1 <- IST1[, c('NM_ESTADO', 'value', 'geometry')]
    m2  <- tm_shape(IST1, name = "Maps") +
      tm_polygons(col = "value", palette = "Blues", title = "")
    tmap_leaflet(m2)
  })

  output$m3 <- renderLeaflet({
    tmap_mode("view")
    IST2 <- inner_join(map, IST2, by = c("NM_ESTADO" = "State"))
    IST2 <- IST2[, c('NM_ESTADO', 'value', 'geometry')]
    m3  <- tm_shape(IST2, name = "Maps") +
      tm_polygons(col = "value", palette = "Oranges", title = "")
    tmap_leaflet(m3)
  })
}

## App ##
shinyApp(ui, server)

see that this is your app and that early on I load the data.frames pre-processed offline to use in the app. See also that I organized your maps in tabItems, one for each map, such that when you click on a tab you show a different map. I also changed the color of the maps to show that each one is a different map.

Your file preparation.R was like this:

## Packages
library(BETS)
library(purrr)
library(sf)

## Maps ##
# States
map <- st_read("Brasil/UFEBRASIL.shp", stringsAsFactors = FALSE)

# Baixando as séries
IST <- BETSget(
  c(15925, 15926, 15927, 15928, 15929,
    15930, 15931, 15932, 15933, 15934,
    15935, 15936, 15937, 15938, 15939,
    15940, 15941, 15942, 15943, 15944,
    15945, 15946, 15947, 15948, 15949,
    15950, 15951),
  data.frame = TRUE)

IST1 <- BETSget(
  c(15861, 15862, 15863, 15864, 15865,
    15866, 15867, 15868, 15869, 15870,
    15871, 15872, 15873, 15874, 15875,
    15876, 15877, 15878, 15879, 15880,
    15881, 15882, 15883, 15884, 15885,
    15886, 15887),
  data.frame = TRUE)

IST2 <- BETSget(
  c(15893, 15894, 15895, 15896, 15897,
    15898, 15899, 15900, 15901, 15902,
    15903, 15904, 15905, 15906, 15907,
    15908, 15909, 15910, 15911, 15912,
    15913, 15914, 15915, 15916, 15917,
    15918, 15919),
  data.frame = TRUE)

## Retirando a última observação e transformando em data.frame
IST  <- map_df(.x = IST,  .f = function(x) x[nrow(x),])
IST1 <- map_df(.x = IST1, .f = function(x) x[nrow(x),])
IST2 <- map_df(.x = IST2, .f = function(x) x[nrow(x),])

## Definindo os nomes da variável para o estado
IST$State <- map$NM_ESTADO
IST1$State <- map$NM_ESTADO
IST2$State <- map$NM_ESTADO

## Retendo somente estados e os valores
IST  <- IST[,c(3,2)]
IST1 <- IST1[,c(3,2)]
IST2 <- IST2[,c(3,2)]

## Salvando os data.frames para uso posterior
save(map, file = 'data/map.rda')
save(IST, file = 'data/IST.rda')
save(IST1, file = 'data/IST1.rda')
save(IST2, file = 'data/IST2.rda')

And finally that’s the behavior of your app:

inserir a descrição da imagem aqui

REMARKS

I believe it is possible to make the app even better and more optimized. As I don’t know exactly what your goals are with this application I limited myself to doing exactly what was in the question.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.