如何将更新的列名从 HandsOnTable 传递到 Shiny 中的绘图?

Posted

技术标签:

【中文标题】如何将更新的列名从 HandsOnTable 传递到 Shiny 中的绘图?【英文标题】:How can I pass updated column names from HandsOnTable to a plot in Shiny? 【发布时间】:2020-10-03 05:12:48 【问题描述】:

我正在构建一个 Shiny 应用程序,它将接收数字数据(以“handsontable”格式)并根据输入的数据制作箱线图。我想有一个选项来更改生成的“handsontable”的列名(作为“textInput”),并将这些名称传递给绘图的“x”轴标签。虽然下面的代码可以很好地更改表中的名称,但我找不到将这些更新的列名(“colHeaders”)传递给绘图的解决方案。我非常感谢您的建议。非常感谢! 编辑:该应用程序还计算列均值并保存 PNG,但这不太可能与我的问题有关

library(shiny)
library(rhandsontable)
library(dplyr)

#UI
ui <- shinyUI(fluidPage(
  titlePanel("Boxplot builder"),
   textOutput('result'),
     sidebarLayout(
        sidebarPanel(
            wellPanel(
               plotOutput("plot")),

            wellPanel(
               h3("Build BoxPlot"), 
                   actionButton("build", "Build")),   

            wellPanel(
               h3("Export Plot"),
                   downloadButton('ExportPlot', 'Export as png')), 
                         ),

            mainPanel(textInput("colnames", "Enter Column Names (separated by comma)", 
                  value="", placeholder = "e.g. Var1, Var2, etc"),
                  h5(tags$b("Enter data")),
                         rHandsontableOutput('table'))
                                  )))

rowNames <- c(sprintf("[%d]",seq(1:20)), "Means")
 defaultDF <- data.frame(
 row.names = rowNames,
 A = rep(NA_integer_, nrow=21),
 B = rep(NA_integer_, 21),
 C = rep(NA_integer_, 21),
  stringsAsFactors = FALSE)

#Server
server <- function(input, output, session)
 (
  values <- reactiveValues(data = defaultDF) 

 observe(
  req(input$table)
  DF <- hot_to_r(input$table)
  DF[setdiff(rowNames, "Means"),]
  DF["Means",] <- colMeans(DF[setdiff(rowNames, "Means"),], na.rm = TRUE)
  values$data <- DF
)

output$table <- renderRHandsontable(
  req(values$data)
  rhandsontable(values$data, rowHeaderWidth = 100, 
  colHeaders=str_trim(unlist(strsplit(input$colnames,","))),) %>%
    hot_row(nrow(values$data), readOnly = TRUE)
) 

observeEvent(input$build,       
  output$plot <- renderPlot(
            boxplot(values$data)
          )
)    

 #Export PNG
  output$ExportPlot = downloadHandler(
  filename = 'BoxPlot.png',
  content = function(file)         
      png(file) 
    boxplot(values$data) 
    dev.off()  
          )                                          
      )

shinyApp(ui = ui, server = server)

【问题讨论】:

嗨,欢迎来到 SO!最好包含一个minimal dataset,人们可以用来思考您的代码。 嗨,希利亚姆!非常感谢!该代码仅生成一个包含 20 行 NaN 和列名的表:A、B、C。最后一行是平均值。然后手动填充该表 【参考方案1】:

您可以将names 添加到您的boxplot 通话中:

boxplot(values$data, names = str_trim(unlist(strsplit(isolate(input$colnames),","))))

并提供来自input$colnames 的列名(用逗号分隔后)。

如果您不想在更改名称时更新绘图,除非按下构建按钮,否则您可以添加 isolate

另外,您可以创建一个单独的reactive 表达式来返回列名,例如:

my_col_names <- reactive(
  str_trim(unlist(strsplit(isolate(input$colnames),",")))
)

然后调用my_col_names(),而不是从绘图、表格和任何您需要列名的地方调用,这样您就不需要重复此代码。请注意,如果在列名更改时应评估此表达式,您可能不希望 isolate

【讨论】:

我还发现,添加第二个观察者,其表达式由 Ben colnames(DF) = str_trim(unlist(strsplit(isolate(input$colnames),","))) 前面加上 req(input$colnames) 可以在表级别完成工作,但现在需要匹配列名的数量正是预建表中的列数。否则,我会收到一个错误“if 中的错误:需要 TRUE/FALSE 的缺失值”,当我完成输入最后一个列名(上例中的第 3 个)时,该错误会消失。 Ben 的解决方案在情节层面上效果最好,这对我来说已经足够好了

以上是关于如何将更新的列名从 HandsOnTable 传递到 Shiny 中的绘图?的主要内容,如果未能解决你的问题,请参考以下文章

Handsontable 如何手动将单元格设置为无效

将列名列表传递给 psycopg2 中的查询

HandsOnTable:如何从 PHP 服务器脚本加载数组?

如何将默认值 0 赋予 Handsontable 中的所有空单元格?

如何将 Handsontable 数据转换回 C# 类

Handsontable:删除行后更新渲染器