英文:
modularise a currently working dropdown "updateSelectInput" shiny input
问题
I have translated the code part as requested:
myProvLists = data %>%
pull(provincia) %>%
unique()
# UI component for the module
ui_location_selections <- function(id) {
ns <- NS(id)
selectInput("provinceSelect", label = "Select Province Data", choices = c(myProvLists))
selectInput("municipioSelect", label = "Select Municipio Variable", choices = c())
# selectInput("distritoSelect", label = "Select Distrito Variable", choices = c())
}
# Server component for the module
server_location_selections <- function(id){
moduleServer(id, function(input, output, session){
observeEvent(input$provinceSelect,{
updateSelectInput(
session,
"municipioSelect",
choices = data %>% filter(provincia == input$provinceSelect) %>% select(municipio) %>% unique() %>% pull(municipio)
)
})
## (1) ## first drop down - observe the selection
observeEvent(input$provinceSelect,{
updateSelectInput(
session,
"municipioSelect",
choices = data %>% filter(provincia == input$provinceSelect) %>% select(municipio) %>% unique() %>% pull(municipio)
)
})
}
)
}
# Call the module in the app
ui <- fluidPage(
ui_location_selections("provincias"),
ui_location_selections("municipios"),
renderUI(output$provincias)
)
server <- function(input, output, session, data) {
server_location_selections("provincias")
}
shinyApp(ui, server)
Please note that the code you provided has some issues, and it seems you are trying to create a Shiny app with modularized UI and server components. However, the code still needs further adjustments to work correctly.
英文:
I have some data which looks like:
# A tibble: 100 × 5
purchase_price provincia municipio distrito zona
<dbl> <chr> <chr> <chr> <chr>
1 207000 Gipuzkoa Bajo Bidasoa Irun Pinar - Anaka - Belaskoenea
2 65000 Valencia Valencia, Zona de Valencia Capital Els Orriols
3 62000 Valencia Valencia, Zona de Valencia Capital Barrio de Benicalap
4 200000 Valencia Valencia, Zona de Valencia Capital Barrio de Benimaclet
5 293000 Málaga Costa del Sol Occidental - Zona de Estepona Estepona Parque Central
6 80000 Araba - Álava Laguardia - Rioja Alavesa Navaridas NA
7 96500 Tarragona Tarragonès Salou Mar i Camp - Platja dels Capellans
8 119500 Jaén Campiña de Jaén Marmolejo NA
9 149999 Tarragona Tarragonès Salou Platja de Llevant
10 144000 Barcelona Maresme Mataró Cerdanyola Sud
I am trying to modularise my code to make it more complete and clean.
For example I am trying to do something where I only define the UI
and observeEvent
once. My current solution I have to define it 3 times and I am trying to clean the code and be more "efficient".
ui_dygraph <- function(id) {
ns <- NS(id)
choices <- map_chr()
tagList(
tags$div(
class = "panel-header",
selectInput(
ns("loc"), "Select dropdown",
choices,
width = NULL,
selectize = TRUE,
selected = choices[[1]]
)
)
)
}
server_dygraph <- function(id){
moduleServer(id, function(input, output, session){
observeEvent()
}
)
}
Shiny App:
library(shiny)
library(tidyverse)
library(bslib)
# data <- ...
ui <- fluidPage(
fluidPage(
theme = bs_theme(bootswatch = "minty"),
title = "hi",
fluidRow(
column(2,
selectInput("provinceSelect", label = "Select Province Data", choices = c()),
selectInput("municipioSelect", label = "Select Municipio Variable", choices = c()),
selectInput("distritoSelect", label = "Select Distrito Variable", choices = c())
)
),
tableOutput('filteredDataOUT')
)
)
server <- function(input, output, session) {
#####################################################################################
################################# Property Search ###################################
#####################################################################################
## (1) ## first drop down - observe the selection
observeEvent(input$provinceSelect,{
updateSelectInput(
session,
"municipioSelect",
choices = data %>% filter(provincia == input$provinceSelect) %>% select(municipio) %>% unique() %>% pull(municipio)
)
})
# then update the second dropdown selections
observe({
updateSelectInput(
session,
"provinceSelect",
choices = data %>% select(provincia) %>% unique() %>% pull(provincia)
)
})
## (1) ## Do the same for the second dropdown
observeEvent(input$municipioSelect,{
updateSelectInput(
session,
"distritoSelect",
choices = data %>% filter(municipio == input$municipioSelect) %>% select(distrito) %>% unique() %>% pull(distrito)
)
})
observe({
updateSelectInput(
session,
"distritoSelect",
choices = data %>% select(municipio) %>% unique() %>% pull(municipio))
})
#### new code
filteredDATA = reactive(
filteredData <- data %>%
filter(provincia == input$provinceSelect & municipio == input$municipioSelect & distrito == input$distritoSelect) %>%
select(-c("provincia", "municipio", "distrito"))
)
output$filteredDataOUT <- renderTable(
filteredDATA()
)
}
shinyApp(ui = ui, server = server)
Data:
data = structure(list(purchase_price = c(207000, 65000, 62000, 2e+05,
293000, 80000, 96500, 119500, 149999, 144000, 298000, 135000,
310000, 285000, 269000, 120000, 595000, 355000, 96000, 490000,
195000, 235000, 197000, 70000, 215000, 169000, 124900, 195000,
185000, 190000, 390348, 113500, 295000, 299995, 156000, 195000,
185000, 260000, 370000, 180000, 105000, 249000, 390000, 295000,
86999, 219900, 264999, 56800, 179900, 150000, 145000, 168500,
160000, 180000, 168000, 42300, 119000, 350000, 390000, 110000,
420000, 154000, 429000, 85000, 259000, 495000, 170000, 102490,
469000, 245000, 138000, 127000, 1390000, 320000, 420000, 292000,
87500, 120000, 475000, 170000, 61000, 255000, 49000, 226000,
220000, 3e+05, 30000, 265000, 330000, 220000, 220000, 139000,
880000, 75000, 220000, 76400, 150000, 46000, 25000, 170000),
provincia = c("Gipuzkoa", "Valencia", "Valencia", "Valencia",
"Málaga", "Araba - Álava", "Tarragona", "Jaén", "Tarragona",
"Barcelona", "Barcelona", "Alicante", "Granada", "Málaga",
"Barcelona", "Tarragona", "Tarragona", "Barcelona", "Valencia",
"Tarragona", "Castellón", "Segovia", "Alicante", "Tarragona",
"Málaga", "Girona", "Cantabria", "Barcelona", "Barcelona",
"Barcelona", "Barcelona", "Sevilla", "Granada", "Barcelona",
"Barcelona", "Cáceres", "Barcelona", "Valencia", "Gipuzkoa",
"Santa Cruz de Tenerife", "Tarragona", "Almería", "Alicante",
"Granada", "Tarragona", "Toledo", "Tarragona", "Huelva",
"Castellón", "Albacete", "Madrid", "Girona", "Castellón",
"Zaragoza", "Madrid", "Alicante", "Barcelona", "Barcelona",
"Sevilla", "Castellón", "Valencia", "Málaga", "Alicante",
"Lleida", "Girona", "Madrid", "Alicante", "Pontevedra", "Barcelona",
"Illes Balears", "Málaga", "A Coruña", "Barcelona", "Barcelona",
"Barcelona", "Málaga", "Cádiz", "Valencia", "Barcelona",
"Toledo", "Castellón", "Barcelona", "Huelva", "Barcelona",
"Tarragona", "A Coruña", "Ciudad Real", "Illes Balears",
"Ourense", "Barcelona", "Barcelona", "Málaga", "Málaga",
"Córdoba", "Tarragona", "Castellón", "Valencia", "Castellón",
"Navarra", "Cádiz"), municipio = c("Bajo Bidasoa", "Valencia, Zona de",
"Valencia, Zona de", "Valencia, Zona de", "Costa del Sol Occidental - Zona de Estepona",
"Laguardia - Rioja Alavesa", "Tarragonès", "Campiña de Jaén",
"Tarragonès", "Maresme", "Maresme", "Marina Baixa", "Vega de Granada",
"Costa del Sol Occidental - Zona de Estepona", "Maresme",
"Tarragonès", "Tarragonès", "Barcelonès", "Horta Nord",
"Tarragonès", "Plana Baixa", "Cuéllar, Zona de", "Alacantí",
"Baix Camp", "Costa del Sol Occidental - Zona de Benalmádena",
"La Selva", "Costa Oriental", "Vallès Oriental", "Vallès Oriental",
"Vallès Oriental", "Maresme", "Sierra Norte", "Vega de Granada",
"Vallès Occidental", "Baix Llobregat Sud", "Llanos de Cáceres",
"Barcelonès", "La Safor", "Donostialdea - Oarsoldea", "Tenerife",
"Tarragonès", "Almería capital y entorno", "Alacantí",
"Vega de Granada", "Tarragonès", "Los Montes de Toledo",
"Tarragonès", "Huelva capital y entorno", "Plana Alta",
"Sierra de Alcaraz - Campo de Montiel", "Zona Sur de Madrid",
"La Selva", "Plana Alta", "Zaragoza, Zona de", "Madrid, Zona de",
"Vega Baja", "Barcelonès", "Bages", "Sevilla capital y entorno",
"Plana Alta", "Valencia, Zona de", "Costa del Sol Occidental - Zona de Estepona",
"Marina Alta", "Segrià", "Alt Empordà", "Madrid, Zona de",
"Marina Baixa", "Comarca de Vigo", "Vallès Occidental",
"Mallorca", "Costa del Sol Occidental - Zona de Estepona",
"Comarca de Ferrol", "Vallès Occidental", "Osona", "Osona",
"Costa del Sol Occidental - Zona de Estepona", "La Janda",
"Ribera Alta (Valencia)", "Osona", "Toledo, Zona de", "Plana Alta",
"Osona", "Huelva capital y entorno", "Vallès Oriental",
"Baix Penedès", "Comarca de Ferrol", "Alcudia (Ciudad Real)",
"Mallorca", "Comarca de Ourense", "Vallès Occidental", "Vallès Occidental",
"Costa del Sol Occidental - Zona de Estepona", "Málaga capital y entorno",
"La Subbética", "Baix Penedès", "Plana Alta", "Valencia, Zona de",
"Plana Baixa", "Comarca de Pamplona", "Campiña de Jerez"
), distrito = c("Irun", "Valencia Capital", "Valencia Capital",
"Valencia Capital", "Estepona", "Navaridas", "Salou", "Marmolejo",
"Salou", "Mataró", "Dosrius", "Benidorm", "Granada Capital",
"Manilva", "Dosrius", "Roda de Berà", "Roda de Berà", "Barcelona Capital",
"Puig", "Tarragona Capital", "Vila-real", "Marugán", "San Vicente del Raspeig / Sant Vicent del Raspeig",
"Mont-roig del Camp", "Benalmádena", "Anglès", "Laredo",
"Granollers", "Granollers", "Granollers", "Cabrils", "El Ronquillo",
"Cenes de la Vega", "Santa Perpètua de Mogoda", "Sant Boi de Llobregat",
"Cáceres Capital", "Barcelona Capital", "Barx", "Donostia - San Sebastián",
"Tacoronte", "Salou", "Almería Capital", "El Campello",
"Albolote", "Salou", "Nambroca", "Salou", "Huelva Capital",
"Castellón de la Plana / Castelló de la Plana", "Alcaraz",
"Fuenlabrada", "Riells i Viabrea", "Castellón de la Plana / Castelló de la Plana",
"Zaragoza Capital", "Madrid Capital", "Torrevieja", "Badalona",
"Castellgalí", "Sevilla Capital", "Cabanes", "Valencia Capital",
"Estepona", "Dénia", "Lleida Capital", "Roses", "Madrid Capital",
"L'Alfàs del Pi", "Vigo", "Sabadell", "Palma de Mallorca",
"Estepona", "Fene", "Cerdanyola del Vallès", "Vic", "Vic",
"Estepona", "Vejer de la Frontera", "Senyera", "Vic", "Toledo Capital",
"Borriol", "Santa Eugènia de Berga", "Huelva Capital", "Sant Celoni",
"Calafell", "Fene", "Almadén", "Palma de Mallorca", "Ourense Capital",
"Terrassa", "Terrassa", "Estepona", "Málaga Capital", "Lucena",
"Calafell", "Castellón de la Plana / Castelló de la Plana",
"Valencia Capital", "Onda", "Pamplona / Iruña", "Jerez de la Frontera"
), zona = c("Pinar - Anaka - Belaskoenea", "Els Orriols",
"Barrio de Benicalap", "Barrio de Benimaclet", "Parque Central",
NA, "Mar i Camp - Platja dels Capellans", NA, "Platja de Llevant",
"Cerdanyola Sud", "Can Massuet del Far", "Levante Alto",
"Centro - Sagrario", "Manilva Pueblo", "Canyamars", NA, NA,
"Vilapicina i la Torre Llobeta", "El Puig", "Llevant", "Centro",
NA, "Centro", "Poble", "Zona Centro Comercial Torrequebrada",
NA, "Zona Playa", "Lledoner", "Lledoner", "Lledoner", NA,
NA, NA, NA, "Casablanca", "Mejostilla", "El Poble Sec - Parc de Montjuïc",
NA, "Amara Zaharra - Arbaizenea", "Campo de Golf - Agua García - Juan Fernández",
"Platja de Llevant", "Plaza de Toros - Santa Rita", "Playa Muchavista",
NA, "Mar i Camp - Platja dels Capellans", NA, "Centre", "Tres Ventanas",
"El Grao", NA, "El Naranjo", NA, "Oeste", "La Magdalena",
"Recoletos", "Zona Carrefour - Urbanizaciones", "Sant Roc",
NA, "Encarnación - Regina", NA, "Penya - Roja - Avda. Francia",
"Bel - Air", "El Montgó", "Mariola", "Centre", "Embajadores - Lavapiés",
"Escandinavia - Cautivador", "Casablanca - Calvario", "Creu Alta",
"Son Serra - Sa Vileta", "Cancelada", NA, "Bellaterra", "El Sucre - El Nadal",
"El Sucre - El Nadal", "Paraiso - Barronal", "Vejer", NA,
"El Sucre - El Nadal", "Santa Bárbara", NA, NA, "La Orden",
NA, "Segur Platja", NA, NA, "Cala Major", "Centro", "Barri del Centre",
"Ca n'Aurell", "Cancelada", "Pinares de San Antón", NA,
"Segur Platja", "Norte", "Beteró", NA, "San Juan", "El Rocío - La Milagrosa"
)), row.names = c(NA, -100L), class = c("tbl_df", "tbl",
"data.frame"))
EDIT:
My attempt which doesn't work:
myProvLists = data %>%
pull(provincia) %>%
unique()
# UI component for the module
ui_location_selections <- function(id) {
ns <- NS(id)
selectInput("provinceSelect", label = "Select Province Data", choices = c(myProvLists))
selectInput("municipioSelect", label = "Select Municipio Variable", choices = c())
# selectInput("distritoSelect", label = "Select Distrito Variable", choices = c())
}
# Server component for the module
server_location_selections <- function(id){
moduleServer(id, function(input, output, session){
observeEvent(input$provinceSelect,{
updateSelectInput(
session,
"municipioSelect",
choices = data %>% filter(provincia == input$provinceSelect) %>% select(municipio) %>% unique() %>% pull(municipio)
)
})
## (1) ## first drop down - observe the selection
observeEvent(input$provinceSelect,{
updateSelectInput(
session,
"municipioSelect",
choices = data %>% filter(provincia == input$provinceSelect) %>% select(municipio) %>% unique() %>% pull(municipio)
)
})
}
)
}
# Call the module in the app
ui <- fluidPage(
ui_location_selections("provincias"),
ui_location_selections("municipios"),
renderUI(output$provincias)
)
server <- function(input, output, session, data) {
server_location_selections("provincias")
}
shinyApp(ui, server)
答案1
得分: 2
以下是代码部分的翻译:
library(shiny)
library(tidyverse)
library(bslib)
# 数据 <- ...
ui <- fluidPage(
fluidPage(
theme = bs_theme(bootswatch = "minty"),
title = "hi",
fluidRow(
column(2,
selectInput("provinceSelect", label = "Select Province Data", choices = data %>% pull(provincia) %>% unique()),
selectInput("municipioSelect", label = "Select Municipio Variable", choices = c()),
selectInput("distritoSelect", label = "Select Distrito Variable", choices = c())
)
),
tableOutput('filteredDataOUT')
)
)
server <- function(input, output, session) {
# 用于在响应式环境中更新和访问数据的响应式值列表
values <- reactiveValues()
## 基于 provinceSelect 过滤数据集,并使用剩余选择项更新 municipioSelect
observeEvent(input$provinceSelect,{
values[['provincia_df']] <- data %>% filter(provincia == input$provinceSelect)
updateSelectInput(
session, "municipioSelect",
choices = values[['provincia_df']] %>% pull(municipio) %>% unique()
)
})
## 也根据 municipioSelect 过滤数据集,并使用剩余选择项更新 distritoSelect
observeEvent(input$municipioSelect,{
values[['municipio_df']] <- values[['provincia_df']] %>% filter(municipio == input$municipioSelect)
updateSelectInput(
session, "distritoSelect",
choices = values[['municipio_df']] %>% pull(distrito) %>% unique()
)
})
# 最终输出由 input$distritoSelect 自动触发
output$filteredDataOUT <- renderTable(
values[['municipio_df']] %>% filter(distrito == input$distritoSelect) %>% select(-all_of(c("provincia", "municipio", "distrito")))
)
}
shinyApp(ui = ui, server = server)
英文:
The solution below is not so much modularisation, but rather a restructuring of the update logic which only requires 2 observeEvent
s and the reactive renderTable
for output.
The key points are
- defining the provincia choices directly in
ui
since they never have to be updated (which you also did in your own attempt) observeEvent
s triggered by the provincia and municipio dropdowns, which subsequently filter the full dataframe based on the choice and update the remaining choices for the next level dropdown menu- no need for an
observeEvent
for the last dropdown in the hierarchy, because thereactiveTable
updates based on this selection anyway
Out of habit, I replaced filteredDATA
with a reactiveValues
list values
to carry intermediate datasets between reactive environments. This could instead always filter directly from data
, so not strictly necessary.
library(shiny)
library(tidyverse)
library(bslib)
# data <- ...
ui <- fluidPage(
fluidPage(
theme = bs_theme(bootswatch = "minty"),
title = "hi",
fluidRow(
column(2,
selectInput("provinceSelect", label = "Select Province Data", choices = data %>% pull(provincia) %>% unique()),
selectInput("municipioSelect", label = "Select Municipio Variable", choices = c()),
selectInput("distritoSelect", label = "Select Distrito Variable", choices = c())
)
),
tableOutput('filteredDataOUT')
)
)
server <- function(input, output, session) {
#reactive value list to update and access data in reactive environments
values <- reactiveValues()
## filter dataset based on provinceSelect, and update municipioSelect with remaining choices
observeEvent(input$provinceSelect,{
values[['provincia_df']] <- data %>% filter(provincia == input$provinceSelect)
updateSelectInput(
session, "municipioSelect",
choices = values[['provincia_df']] %>% pull(municipio) %>% unique()
)
})
## filter dataset also on municipioSelect, and update distritoSelect with remaining choices
observeEvent(input$municipioSelect,{
values[['municipio_df']] <- values[['provincia_df']] %>% filter(municipio == input$municipioSelect)
updateSelectInput(
session, "distritoSelect",
choices = values[['municipio_df']] %>% pull(distrito) %>% unique()
)
})
# final output is automaticall triggered by input$distritoSelect
output$filteredDataOUT <- renderTable(
values[['municipio_df']] %>% filter(distrito == input$distritoSelect) %>%
select(-all_of(c("provincia", "municipio", "distrito")))
)
}
shinyApp(ui = ui, server = server)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论