简体   繁体   English

R Shiny:使用逻辑条件从 checkboxGroupInput() 反应性地子集数据帧

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM