[英]R Shiny: reactively subset a data frame from checkboxGroupInput() using logical conditions
I have a Shiny app with a checkboxGroupInput() in the UI where the user selects any prior cancers they have had.我有一个 Shiny 应用程序,在 UI 中有一个 checkboxGroupInput() ,用户可以在其中选择他们以前患有的任何癌症。 My data frame has a column named "cancer" that has nine different cancer types.我的数据框有一个名为“cancer”的列,其中包含九种不同的癌症类型。 When the user selects their prior cancers, I want to remove those rows from the data frame.当用户选择他们之前的癌症时,我想从数据框中删除这些行。 Conversely, if they unselect a cancer, then the row should automatically be added back into the data frame.相反,如果他们取消选择癌症,则该行应自动添加回数据框中。 The data frame also needs to be called by other functions in the server later on for plotting.数据框也需要稍后由服务器中的其他函数调用以进行绘图。
I was able to reactively subset the data frame by variables like gender and age fairly easily using logical arguments:我能够使用逻辑 arguments 相当容易地通过性别和年龄等变量对数据框进行反应性子集化:
tmp.df <- reactive({
lynch.data[which(lynch.data$gender == input$gender & lynch.data$age == input$age),]
})
The problem with cancers is that the person may have had anywhere between 0 and 9 unique cancer types.癌症的问题在于,这个人可能患有 0 到 9 种独特的癌症类型。 I would need a variable number of OR statements based on the selection.根据选择,我需要可变数量的 OR 语句。 In order to do that I have been playing with different variants of this code snipet as a logical argument without success:为了做到这一点,我一直在使用此代码片段的不同变体作为逻辑参数,但没有成功:
str2lang(paste0("lynch.data$cancer != ",input$cancer, collapse = " | "))
Below is a code excerpt of the relevant sections.以下是相关部分的代码摘录。 I have tried making my data frame both a reactive function and a reactiveValue without success.我尝试让我的数据框既是反应性的 function 又是反应性的值,但没有成功。 This excerpt below shows the reactiveValue version.下面的这段摘录显示了 reactiveValue 版本。
UI:用户界面:
library(shiny)
load("Cancer_Data.RData") # lynch.data is the object name that is loaded
ui <- fluidPage(
# App title
titlePanel("Risk Calculator"),
# Sidebar layout with input and output definitions
sidebarLayout(
# Sidebar panel for inputs
sidebarPanel(
radioButtons(inputId = "gender", label = "Sex:",
choices = c("Female","Male")),
sliderInput(inputId = "age", label = "Current Age:",
min = 1, max = 110, value = 25),
checkboxGroupInput(inputId = "cancer", label = "Prior Cancers (check all that apply):",
choices = c("Colorectal","Brain","Endometrial","Gastric","Ovarian","Pancreatic",
"Small Intestine","Upper Urinary Tract","Urinary Bladder")),
actionButton("calc","Calculate")
),
# Main panel for displaying outputs
mainPanel(
#Output: Output table
tableOutput(outputId = "table")
)))
Server:服务器:
server <- function(input, output) {
rv <- reactiveValues(tmp.df = lynch.data[which(lynch.data$gender == input$gender &
lynch.data$age == input$age),])
observeEvent(input$calc,{
rv$tmp.df <- if(length(input$cancer) != 0){
tmp.df <- lynch.data[which(lynch.data$gender == input$gender &
lynch.data$age == input$age &
str2lang(paste0("lynch.data$cancer != ",input$cancer, collapse = " | "))),]
} else {
tmp.df <- lynch.data[which(lynch.data$gender == input$gender &
lynch.data$age == input$age),]
}
})
output$table <- renderTable({head(rv$tmp.df,20)})
}
Thanks in advance!提前致谢!
I found a fairly simple solution: Instead of wrapping the data frame in reactiveValues() I just used a reactive function instead.我找到了一个相当简单的解决方案:我没有将数据框包装在 reactiveValues() 中,而是使用了反应式 function。 I first subset the dataframe based on variables with a single condition.我首先根据具有单个条件的变量对 dataframe 进行子集化。 Within the same function, I then iteratived using a for loop to remove each cancer in input$cancer.在同一个 function 中,然后我使用 for 循环迭代以删除 input$cancer 中的每个癌症。 Anywhere else I need to refer to the data frame I just call tmp.df()在其他任何地方我需要参考我刚刚调用的数据框 tmp.df()
tmp.df <- reactive({
all.cancers <- lynch.data[which(lynch.data$gender == input$gender &
lynch.data$age == input$age),]
for (cancer in input$cancer) {
all.cancers <- all.cancers[-which(all.cancers$cancer == cancer),]
}
all.cancers
})
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.