当我对数据框进行更改时,Shiny 中 1 个选择器输入的输出会自动更新

Posted

技术标签:

【中文标题】当我对数据框进行更改时,Shiny 中 1 个选择器输入的输出会自动更新【英文标题】:Output from 1 pickerInput in Shiny automatically updates when I do changes in the dataframe 【发布时间】:2021-10-14 16:29:18 【问题描述】:

最近我问我pickerInput 有问题。问题是solved,但我想知道如何在一个反应​​函数中只包含数据而不创建另一个 + 两个非数字列。

在这个post 中,我在反应函数中使用了 mtcars(模拟我在上传文件时通常会做的事情),然后在另一个反应函数中,我正在对数据帧(日志和 sqrt)进行更改。 但是,我想添加两个非数字列,这必须在转换后完成。

dat <- mtcars
dat$Brands <- rownames(dat)
str(dat$Brands)

> chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive"
> "Hornet Sportabout" "Valiant" "Duster 360" "Merc 240D" ...

dat$Info <- rep("Info", length(rownames(mtcars)))
str(dat$Info)

>  chr [1:32] "Info" "Info" "Info" "Info" "Info" "Info" "Info" "Info"
> "Info" "Info" "Info" "Info" "Info" "Info" "Info" "Info" ...

在那篇文章中,如果我在 data1() 中添加两个非数字列,并在他们回答我时将 pickerInput 与 data() 一起留下,则非数字列将不会出现选择。 出于这个原因,我将所有信息放在一个反应​​函数中......但是,现在解决方案不起作用。

每次我点击一个checkboxInput 时,选定的列都会自动更改。

这是代码:

library(shiny)
library(shinyWidgets)
library(dplyr)

ui <- fluidPage(
  
  # Application title
  titlePanel("Old Faithful Geyser Data"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      
      uiOutput("picker"),
      
      checkboxInput("play", strong("I want to play with my data"), value = FALSE),
      
      conditionalPanel(
        condition = "input.play == 1",
        checkboxInput("change_log2", "Log2 transformation", value = FALSE),
        checkboxInput("run_sqrt", "sqrt option", value = FALSE)),
      
      
      actionButton("view", "View Selection")
      
    ),
    
    # Show a plot of the generated distribution
    mainPanel(
      h2('Mydata'),
      DT::dataTableOutput("table"),
    )
  )
)

library(shiny)
library(DT)

server <- function(session, input, output) 
  
  data <- reactive(
    dat <- mtcars
    if(input$change_log2)
      dat <- log2(dat)
    
    
    if(input$run_sqrt)
      dat <- sqrt(dat)
    
    
    dat$Brands <- rownames(dat)
    dat$Info <- rep("Info", length(rownames(mtcars)))
    
    return(dat)
  )
  
  
  observeEvent(input$play, 
    
    if(!input$play) 
      updateCheckboxInput(session, "change_log2", value = FALSE)
      updateCheckboxInput(session, "run_sqrt", value = FALSE)
    
    
  )
  
  
  output$picker <- renderUI(
    pickerInput(inputId = 'pick', 
                label = 'Choose', 
                choices = colnames(data()),
                options = list(`actions-box` = TRUE),
                multiple = T,
                selected = colnames(data())
    )
  )
  
  datasetInput <- eventReactive(input$view,
    
    datasetInput <- data() %>% 
      select(input$pick)
    
    return(datasetInput)
    
  )
  
  output$table <- renderDT(
    
    datatable(
      datasetInput(),
      filter="top", 
      rownames = FALSE,
      extensions = 'Buttons',
      
      options = list(
        dom = 'Blfrtip',
        buttons =
          list('copy', 'print', list(
            extend = 'collection',
            buttons = list(
              list(extend = 'csv', filename = "File", title = NULL),
              list(extend = 'excel', filename = "File", title = NULL)),
            text = 'Download'
          ))
      ),
      class = "display"
    )
  )



# Run the application 
shinyApp(ui = ui, server = server)

我想它必须与updatepickerInput 相关(我看到类似的问题,如this,但我不知道如何在独特的pickerInput 中做到这一点。

有人知道怎么解决吗?

提前致谢

问候

【问题讨论】:

【参考方案1】:

您可以使用reactiveValues 保存数据集,并将函数仅应用于pickerInput 中选定列的数字列。

library(shiny)
library(shinyWidgets)
library(dplyr)
library(DT)

dat <- mtcars
dat$Brands <- rownames(dat)
dat$Info <- rep("Info", length(rownames(mtcars)))


ui <- fluidPage(
  
  # Application title
  titlePanel("Old Faithful Geyser Data"),
  
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      
      uiOutput("picker"),
      
      checkboxInput("play", strong("I want to play with my data"), value = FALSE),
      
      conditionalPanel(
        condition = "input.play == 1",
        checkboxInput("change_log2", "Log2 transformation", value = FALSE),
        checkboxInput("run_sqrt", "sqrt option", value = FALSE)),
      
      
      actionButton("view", "View Selection")
      
    ),
    
    # Show a plot of the generated distribution
    mainPanel(
      h2('Mydata'),
      DT::dataTableOutput("table"),
    )
  )
)


server <- function(session, input, output) 
  
  rv <- reactiveValues(data = dat)
  
  observeEvent(input$play, 
    
    if(!input$play) 
      updateCheckboxInput(session, "change_log2", value = FALSE)
      updateCheckboxInput(session, "run_sqrt", value = FALSE)
    
    
  )
  
  
  output$picker <- renderUI(
    cols <- names(rv$data)
    
    pickerInput(inputId = 'pick', 
                label = 'Choose', 
                choices = cols,
                options = list(`actions-box` = TRUE),
                multiple = T,
                selected = cols)
  )
  
  datasetInput <- eventReactive(input$view,
    
    datasetInput <- rv$data %>% select(input$pick)
    if(input$change_log2)
      datasetInput <- datasetInput %>% mutate(across(where(is.numeric), log2))
    
    
    if(input$run_sqrt)
      datasetInput <- datasetInput %>% mutate(across(where(is.numeric), sqrt))
    

    return(datasetInput)
    
  )
  
  output$table <- renderDT(
    
    datatable(
      datasetInput(),
      filter="top", 
      rownames = FALSE,
      extensions = 'Buttons',
      
      options = list(
        dom = 'Blfrtip',
        buttons =
          list('copy', 'print', list(
            extend = 'collection',
            buttons = list(
              list(extend = 'csv', filename = "File", title = NULL),
              list(extend = 'excel', filename = "File", title = NULL)),
            text = 'Download'
          ))
      ),
      class = "display"
    )
  )



# Run the application 
shinyApp(ui = ui, server = server)

【讨论】:

非常感谢您的回答...但是...是否可以在PickerInput 选项中选择非数字列?因为我希望用户可以选择查看品牌和信息列,如果用户不选择该选项,她/他将看不到这些列...例如,为了根据用户的决定获取带有或不带有这些列的 csv 文件。 非常感谢您的帮助。但是,您知道是否有可能做同样的事情,但在添加非数字列之前进行转换?因为我不能对所有内容都使用此步骤 `datasetInput %>% mutate(across(where(is.numeric), sqrt))`,因为我有一些函数不适用于 mutate 或 sapply。我不能举出函数的例子,因为它们是敏感信息。我认为解决方案与更新input$pickupdatePickerInput...有关,但我想不出其他办法。

以上是关于当我对数据框进行更改时,Shiny 中 1 个选择器输入的输出会自动更新的主要内容,如果未能解决你的问题,请参考以下文章

当我有选择 > 1000 时,Shiny 不会向我显示整个 selectInput

R Shiny Dynamic选择输入 - 捕获事件

如果用户写入超过 1 列,如何从 Shiny 的数据框中选择列?

如何从 Shiny 中的下拉框中根据变量选择动态创建直方图

使用inputBox的输出作为R Shiny中inputSlider的输入

当我在 mkMapView 中更改段时无法更改引脚颜色