【问题标题】:Reading objects from shiny output object not allowed?不允许从闪亮的输出对象中读取对象?
【发布时间】:2017-01-03 15:30:13
【问题描述】:

我正在尝试编写一个小应用程序,允许用户制作散点图,选择绘图上的点子集,然后以 .csv 格式输出仅包含这些选定点的表格。我想出了如何启动和运行页面以及如何使用brushedPoints 选择点。出现带有选定点的表,但是当我按下下载按钮时,出现错误“不允许从闪亮输出对象中读取对象”。出现。我是否无法以 .csv 格式下载我可以在屏幕上直观看到的表格?如果是这样,是否有解决方法?

我使用下面的 iris 数据集重新创建了问题。任何帮助弄清楚为什么我不能下载显示的行表将不胜感激。

data(iris)

ui <- basicPage(
  plotOutput("plot1", brush = "plot_brush"),
  verbatimTextOutput("info"),mainPanel(downloadButton('downloadData', 'Download'))
)


server <- function(input, output) {
  output$plot1 <- renderPlot({
ggplot(iris,aes(x=Sepal.Width,y=Sepal.Length)) +
    geom_point(aes(color=factor(Species))) + 
    theme_bw()
  })

  output$info <- renderPrint({
brushedPoints(iris, input$plot_brush, xvar = "Sepal.Width", yvar = "Sepal.Length")
  })

  output$downloadData <- downloadHandler(
      filename = function() { 
        paste('SelectedRows', '.csv', sep='') },
        content = function(file) {
        write.csv(output$info, file)
      }
  )

}


shinyApp(ui, server)

【问题讨论】:

    标签: r shiny scatter-plot shiny-server


    【解决方案1】:

    问题是输出对象也在生成所有的网络显示内容。相反,您需要单独提取数据以进行下载。您可以在下载代码中再次调用brushedPoints 来完成此操作。然而,更好的是使用reactive() 函数只执行一次,然后在您需要的任何地方调用它。以下是我将如何修改您的代码以使其正常工作:

    data(iris)
    
    ui <- basicPage(
      plotOutput("plot1", brush = "plot_brush"),
      verbatimTextOutput("info"),mainPanel(downloadButton('downloadData', 'Download'))
    )
    
    
    server <- function(input, output) {
      output$plot1 <- renderPlot({
        ggplot(iris,aes(x=Sepal.Width,y=Sepal.Length)) + geom_point(aes(color=factor(Species))) + theme_bw()
      })
    
    
      selectedData <- reactive({
        brushedPoints(iris, input$plot_brush)
      })
    
      output$info <- renderPrint({
        selectedData()
      })
    
      output$downloadData <- downloadHandler(
        filename = function() { 
          paste('SelectedRows', '.csv', sep='') },
        content = function(file) {
          write.csv(selectedData(), file)
        }
      )
    
    }
    
    
    shinyApp(ui, server)
    

    (注意,使用ggplot2,您不需要在brushedPoints 中显式设置xvaryvar。因此,我在此处将其删除以增加代码的灵活性。)

    我不知道shiny 有任何“套索”风格的免费绘图功能(不过,给它一个星期——他们不断地添加有趣的工具)。但是,您可以通过允许用户选择多个区域和/或单击单个点来模仿行为。服务器逻辑变得更加混乱,因为您需要将结果存储在 reactiveValues 对象中以便能够重复使用它。我做了类似的事情,允许我在一个图上选择点并在其他图上突出显示/删除它们。这比你在这里需要的更复杂,但下面应该可以工作。您可能想要添加其他按钮/逻辑(例如,“重置”选择),但我相信这应该可行。我确实在绘图中添加了选择的显示,以便您跟踪已选择的内容。

    data(iris)
    
    ui <- basicPage(
      plotOutput("plot1", brush = "plot_brush", click = "plot_click")
      , actionButton("toggle", "Toggle Seletion")
      , verbatimTextOutput("info")
      , mainPanel(downloadButton('downloadData', 'Download'))
    )
    
    
    server <- function(input, output) {
      output$plot1 <- renderPlot({
    
        ggplot(withSelected()
               , aes(x=Sepal.Width
                     , y=Sepal.Length
                     , color=factor(Species)
                     , shape = Selected)) +
          geom_point() +
          scale_shape_manual(
            values = c("FALSE" = 19
                       , "TRUE" = 4)
          , labels = c("No", "Yes")
          , name = "Is Selected?"
          ) +
          theme_bw()
      })
    
      # Make a reactive value -- you can set these within other functions
      vals <- reactiveValues(
        isClicked = rep(FALSE, nrow(iris))
      )
    
    
      # Add a column to the data to ease plotting
      # This is really only necessary if you want to show the selected points on the plot
      withSelected <- reactive({
        data.frame(iris
                   , Selected = vals$isClicked)
      })
    
    
    
      # Watch for clicks
      observeEvent(input$plot_click, {
    
        res <- nearPoints(withSelected()
                          , input$plot_click
                          , allRows = TRUE)
    
        vals$isClicked <-
          xor(vals$isClicked
              , res$selected_)
      })
    
    
      # Watch for toggle button clicks
      observeEvent(input$toggle, {
        res <- brushedPoints(withSelected()
                             , input$plot_brush
                             , allRows = TRUE)
    
        vals$isClicked <-
          xor(vals$isClicked
              , res$selected_)
      })
    
      # pull the data selection here
      selectedData <- reactive({
        iris[vals$isClicked, ]
      })
    
      output$info <- renderPrint({
        selectedData()
      })
    
      output$downloadData <- downloadHandler(
        filename = function() { 
          paste('SelectedRows', '.csv', sep='') },
        content = function(file) {
          write.csv(selectedData(), file)
        }
      )
    
    }
    
    
    shinyApp(ui, server)
    

    【讨论】:

    • 马克,这很好用!反应功能特别有用,感谢您引起我的注意。非常感谢。
    • 马克,我突然想到,brushedPoints 选项只允许用户选择矩形内的点。是否有可能的“套索”选项?我四处搜索,但除了 Plot.ly 中的“套索”选项外找不到任何东西,这需要对上述脚本进行大量重写。
    • 不是直接的,我知道。但是,我只是添加了一个显示如何进行多项选择的编辑 - 最终可能会给您相同的行为。
    • 马克,您的解决方案非常适合我。我不能感谢你。多项选择确实给出了与我希望通过套索实现的相同的行为。我特别喜欢你如何配置它,以便标记根据它们是否被选中而改变形状。我希望通过更多的练习,我可以开始制作像这样更复杂的应用程序。谢谢。
    猜你喜欢
    • 2014-12-04
    • 2020-04-04
    • 2021-07-18
    • 2020-02-29
    • 2018-10-29
    • 2017-01-27
    • 2017-09-19
    • 1970-01-01
    • 2015-04-13
    相关资源
    最近更新 更多