在Shiny R中更新绘图输出。

3
对于我正在开发的Shiny应用程序,给定一个数据文件,我需要在应用程序的起始页面上显示条形图(我使用ggplot2)。因此,当用户运行应用程序并上传文件时,他们将立即在主面板中看到条形图。
应用程序启动后,用户应该能够点击一个actionButton来引导数据并向同一条形图添加误差线。我不想一开始就添加误差线,因为我的用户可能对误差线不感兴趣,并且使用自助法添加误差线会让他们等待。因此,只有他们想要看到它并愿意等待自助法结束,我才必须添加误差线。
我尝试了很多方法来更新绘图,但没有成功。当然,我可以呈现带有误差线的另一个绘图,但这不是我理想情况下想做的事情。是否有一种方法可以更新绘图或向其添加功能?

请提供一个可重现的示例,以便我们可以在其基础上构建。 - Bahae Omid
感谢您关注这个问题。有人以解决我的问题的方式回答了它 :) - Mr K
2个回答

2

我认为你总是需要通过renderPlot来更新绘图输出(除非你将绘图保存为图像,并在不可见的div中加载它,然后在其上叠加你的绘图)。你可以将绘图的层分开保存成两部分,一部分是条形图,一部分是误差线,如果需要,只需将误差线叠加在上面。

data(iris)
require(shiny)

sepal.length <- sapply(unique(iris$Species),function(s){ iris[which(iris$Species==s),"Sepal.Length"] })
data         <- data.frame("mean"=apply(sepal.length,2,mean),"sd"=apply(sepal.length,2,sd),"species"=unique(iris$Species))

server <- shinyServer(function(input, output, session) {

  # Save plot in reactive
  plot.dat <- reactiveValues(main=NULL, layer1=NULL)
  plot.dat$main <- ggplot(data=data,aes(x=species,y=mean,fill=species)) + 
    geom_bar(stat="identity") 

  observe({
    print("render")
    output$plot <- renderPlot({ plot.dat$main + plot.dat$layer1 })
  })

  observeEvent(input$add_bars,{
    # Calculate standard deviation
    plot.dat$layer1 <- geom_errorbar(aes(ymin=mean-sd,ymax=mean+sd))
  })
})

ui <- shinyUI(fluidPage(
  plotOutput("plot"),
  actionButton("add_bars","Add error bars")
))

shinyApp(ui = ui, server = server)  

谢谢!这就是我想要做的事情,把图形分成两个部分,但我不知道在Shiny环境下如何正确地实现它。 - Mr K
你好,虽然你的回答有所帮助,但我仍然有一些问题没有解决。你在使用mean和sd之前在全局环境中定义了它们。然而,在观察到“input$add_bars”事件之后,我需要计算标准差,然后将其附加到“data”中,以便在添加带误差线的层之前使用。我一直没有成功。你能帮我吗?非常感谢! - Mr K
实际上我终于搞明白了。我在事件观察器中定义了一个新的数据框,其中包含平均值和标准差值,并更新了观察器中的两个层,而不是仅更新带有误差条的层。虽然这样可以工作,但我想知道当用户更改输入的数据文件时是否会遇到问题。无论如何,在输入新文件后,先前数据集的带误差栏的图层仍然保持引导,从而导致新数据文件的错误误差栏。这比我想象的要复杂。 - Mr K
你可以在读入新数据时将 plot.dat$layer1 设置为 NULL。根据你的代码,更改数据集可能会导致错误。如果你能给我一个例子,我很乐意快速查看一下。 - RmIu
我考虑过这个问题。但是问题是如何检测新的文件输入。我的文件输入与此演示中的操作方式相同:链接 - Mr K
read.csv 调用之前,您可以始终将 plot.dat$layer1 设置为 NULL。 - RmIu

0

我尝试使用Plotly在shiny中实现这一点,但没有像上面展示的那样使用layers。虽然这可能是一个旧的主题,但对于其他人可能有帮助。

在以下示例中:

  • 首先显示基于一个人的成绩的图表。
  • 然后,随着我们从列表中选择输入,其他人的分数更新在同一张图表上
library(shiny)
library(plotly)

ui <- fluidPage(
  selectizeInput(
    inputId = "Player",
    selected = NULL,
    multiple = TRUE,
    label = " Choose Player",
    choices = c("Sam", "Bennet", "Orlando"),
    options = list('plugins' = list('remove_button'))
  ),
  plotlyOutput("Plot1")
)

server <- function(input, output, session) {
  output$Plot1 <-  renderPlotly({
    
    scores <- data.frame(Name = c("Sam", "Bennet", "Orlando", "Sam", "Bennet", "Orlando", "Sam", "Bennet", "Orlando" ), 
                        Number= c(47, 35, 40, 49, 32, 31, 51, 49, 44 ),
                        Year = c("2018","2018","2018", "2017", "2017", "2017", "2016","2016","2016")
    )  
    
    chris_goals <- data.frame(Name = c("Chris", "Chris", "Chris"), 
                        Number= c(90, 95, 100 ),
                        Year = c("2018","2017","2016")
    ) 
    
    filteredScores <- reactive({
      
      plot_ly(chris_goals, x = ~Year, y = ~Number, type = 'scatter', mode = 'lines', color = ~Name)%>% layout(showlegend = TRUE) %>%
        layout(title = 'Scores') %>%
        add_trace(data =  scores[scores$Name %in% input$Player, ], x = ~Year, y = ~Number, type = 'scatter', mode = 'lines', color = ~Name)
    })
    
    filteredScores()
  })
}
shinyApp(ui, server)

默认值: 输入图像描述

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接