过滤dataframe的两个属性时同步两个selectinput(多选)
Synchronise two selectizeInputs when filtering two attributes of a data frame (mulitple selection)
在我的 shinydashboard 应用程序中,我想为用户提供按替代属性过滤数据框的选项。我的数据框在 1:1 关系中有一个“ID”列和一个“名称”列。使用两个 selectizeInputs,用户可以通过一个或另一个来过滤天气。
我现在想要实现的是在选择其中一个项目时更新另一个 selectizeInput。所以两个 selectizeInputs 都显示数据框的相应项目。我设法解决了这个问题,只要我将选择限制为单个项目,而不是多项选择。
以下最小代码是目前为止我能得到的最接近的代码,但它不允许多项选择。显然是由于一种死锁情况,即第一个选择的项目导致另一个 seletizeInput 过滤相同的元素,自动将第一个 selectizeInput 再次更新为这个单个项目。
library(shiny)
library(shinydashboard)
library(tidyverse)
ui <- dashboardPage(
dashboardHeader(title = 'Test alternative select') ,
dashboardSidebar(
sidebar <- dashboardSidebar(
sidebarMenu(
selectizeInput(inputId = 'id' ,
label = 'ID' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button'))) ,
selectizeInput(inputId = 'name' ,
label = 'Name' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button')))
))) ,
dashboardBody()
)
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observe({
if (is.null(input$id)) {
updateSelectizeInput(session = session ,
inputId = 'name' ,
choices = data$Name ,
options = list(plugins= list('remove_button')))
} else {
choices <- data %>%
filter(ID %in% input$id) %>%
pull(Name)
updateSelectizeInput(session = session ,
inputId = 'name' ,
choices = choices ,
selected = choices ,
options = list(plugins= list('remove_button')))
}
})
observe({
if (is.null(input$name)) {
updateSelectizeInput(session = session ,
inputId = 'id' ,
choices = data$ID ,
options = list(plugins= list('remove_button')))
} else {
choices <- data %>%
filter(Name %in% input$name) %>%
pull(ID)
updateSelectizeInput(session = session ,
inputId = 'id' ,
choices = choices ,
selected = choices ,
options = list(plugins= list('remove_button')))
}
})
}
shinyApp(ui, server)
我不确定这是否可以通过这种方式解决,但如果“是”,我可能不得不以某种方式使用“隔离”。但是我想不通。
经过一些尝试和错误后,我找到了一个解决方案,对我的代码进行了以下更改。基本上我使用 observeEvent 而不是 observe.
我用 freezeReactiveValue()
尝试了 kenshuri 的提示(感谢),但它没有帮助,甚至变得更糟。
下面的解决方案确实是我想要实现的。唯一剩下的问题:
当删除一个框中的所有项目时,最后一个保留在另一个框中。但我可以接受。
library(shiny)
library(shinydashboard)
library(tidyverse)
ui <- dashboardPage(
dashboardHeader(title = 'Test alternative select') ,
dashboardSidebar(
sidebar <- dashboardSidebar(
sidebarMenu(
selectizeInput(inputId = 'id' ,
label = 'ID' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button'))) ,
selectizeInput(inputId = 'name' ,
label = 'Name' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button')))
))) ,
dashboardBody()
)
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observe({
if (is.null(input$id) & is.null(input$name)) {
updateSelectizeInput(session , 'name' , choices = data$Name , selected = NULL)
updateSelectizeInput(session , 'id' , choices = data$ID , selected = NULL)
}
})
observeEvent(input$id, {
sel <- data %>% filter(ID %in% input$id) %>% pull('Name')
updateSelectizeInput(session , 'name' , selected = isolate(sel))
})
observeEvent(input$name, {
sel <- data %>% filter(Name %in% input$name) %>% pull('ID')
updateSelectizeInput(session , 'id' , selected =isolate(sel))
})
}
shinyApp(ui, server)
也许您正在寻找这个
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observeEvent(input$id, {
if (is.null(input$id)) {
updateSelectizeInput(session , 'name' , choices = data$Name , selected = NULL)
} else{
sel <- data %>% filter(ID %in% input$id) %>% pull('Name')
updateSelectizeInput(session , 'name' , selected = isolate(sel))
}
print(input$id)
}, ignoreNULL = FALSE)
observeEvent(input$name, {
if (is.null(input$name)) {
updateSelectizeInput(session , 'id' , choices = data$ID , selected = NULL)
} else {
sel <- data %>% filter(Name %in% input$name) %>% pull('ID')
updateSelectizeInput(session , 'id' , selected =isolate(sel))
}
}, ignoreNULL = FALSE)
}
在我的 shinydashboard 应用程序中,我想为用户提供按替代属性过滤数据框的选项。我的数据框在 1:1 关系中有一个“ID”列和一个“名称”列。使用两个 selectizeInputs,用户可以通过一个或另一个来过滤天气。
我现在想要实现的是在选择其中一个项目时更新另一个 selectizeInput。所以两个 selectizeInputs 都显示数据框的相应项目。我设法解决了这个问题,只要我将选择限制为单个项目,而不是多项选择。
以下最小代码是目前为止我能得到的最接近的代码,但它不允许多项选择。显然是由于一种死锁情况,即第一个选择的项目导致另一个 seletizeInput 过滤相同的元素,自动将第一个 selectizeInput 再次更新为这个单个项目。
library(shiny)
library(shinydashboard)
library(tidyverse)
ui <- dashboardPage(
dashboardHeader(title = 'Test alternative select') ,
dashboardSidebar(
sidebar <- dashboardSidebar(
sidebarMenu(
selectizeInput(inputId = 'id' ,
label = 'ID' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button'))) ,
selectizeInput(inputId = 'name' ,
label = 'Name' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button')))
))) ,
dashboardBody()
)
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observe({
if (is.null(input$id)) {
updateSelectizeInput(session = session ,
inputId = 'name' ,
choices = data$Name ,
options = list(plugins= list('remove_button')))
} else {
choices <- data %>%
filter(ID %in% input$id) %>%
pull(Name)
updateSelectizeInput(session = session ,
inputId = 'name' ,
choices = choices ,
selected = choices ,
options = list(plugins= list('remove_button')))
}
})
observe({
if (is.null(input$name)) {
updateSelectizeInput(session = session ,
inputId = 'id' ,
choices = data$ID ,
options = list(plugins= list('remove_button')))
} else {
choices <- data %>%
filter(Name %in% input$name) %>%
pull(ID)
updateSelectizeInput(session = session ,
inputId = 'id' ,
choices = choices ,
selected = choices ,
options = list(plugins= list('remove_button')))
}
})
}
shinyApp(ui, server)
我不确定这是否可以通过这种方式解决,但如果“是”,我可能不得不以某种方式使用“隔离”。但是我想不通。
经过一些尝试和错误后,我找到了一个解决方案,对我的代码进行了以下更改。基本上我使用 observeEvent 而不是 observe.
我用 freezeReactiveValue()
尝试了 kenshuri 的提示(感谢),但它没有帮助,甚至变得更糟。
下面的解决方案确实是我想要实现的。唯一剩下的问题: 当删除一个框中的所有项目时,最后一个保留在另一个框中。但我可以接受。
library(shiny)
library(shinydashboard)
library(tidyverse)
ui <- dashboardPage(
dashboardHeader(title = 'Test alternative select') ,
dashboardSidebar(
sidebar <- dashboardSidebar(
sidebarMenu(
selectizeInput(inputId = 'id' ,
label = 'ID' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button'))) ,
selectizeInput(inputId = 'name' ,
label = 'Name' ,
choices = NULL ,
selected = NULL ,
multiple = TRUE ,
options = list(plugins = list('remove_button')))
))) ,
dashboardBody()
)
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observe({
if (is.null(input$id) & is.null(input$name)) {
updateSelectizeInput(session , 'name' , choices = data$Name , selected = NULL)
updateSelectizeInput(session , 'id' , choices = data$ID , selected = NULL)
}
})
observeEvent(input$id, {
sel <- data %>% filter(ID %in% input$id) %>% pull('Name')
updateSelectizeInput(session , 'name' , selected = isolate(sel))
})
observeEvent(input$name, {
sel <- data %>% filter(Name %in% input$name) %>% pull('ID')
updateSelectizeInput(session , 'id' , selected =isolate(sel))
})
}
shinyApp(ui, server)
也许您正在寻找这个
server <- function(input, output , session) {
data <- tribble(
~ID , ~Name ,
'1' , 'France' ,
'2' , 'Italy' ,
'3' , 'Germany' ,
'4' , 'Spain' ,
'5' , 'Portugal'
)
observeEvent(input$id, {
if (is.null(input$id)) {
updateSelectizeInput(session , 'name' , choices = data$Name , selected = NULL)
} else{
sel <- data %>% filter(ID %in% input$id) %>% pull('Name')
updateSelectizeInput(session , 'name' , selected = isolate(sel))
}
print(input$id)
}, ignoreNULL = FALSE)
observeEvent(input$name, {
if (is.null(input$name)) {
updateSelectizeInput(session , 'id' , choices = data$ID , selected = NULL)
} else {
sel <- data %>% filter(Name %in% input$name) %>% pull('ID')
updateSelectizeInput(session , 'id' , selected =isolate(sel))
}
}, ignoreNULL = FALSE)
}