简体   繁体   English

在 Shiny 中具有反应性数据框的反应性 ggplot

[英]Reactive ggplot with reactive data frame in Shiny

This is a follow on post to one I made here .这是我在此处制作的帖子的后续内容。 The original question required the user to input some values into some text boxes/numeric boxes compute some function and then display the result in a data frame.原始问题要求用户在一些文本框/数字框中输入一些值,计算一些 function,然后在数据框中显示结果。 It can be computed using the following R code (which also includes the ggplot2 plot I would also like to add).它可以使用以下 R 代码(还包括ggplot2 plot 我还想添加)来计算。

R Code: R 代码:

someFunction <- function(S, K, type){
  
  # call option
  if(type=="C"){
    d1 <- S/K
    value <- S*pnorm(d1) - K*pnorm(d1)
    return(value)}
  
  # put option
  if(type=="P"){
    d1 <- S*K
    value <-  (K*pnorm(d1) - S*pnorm(d1))
    return(value)}
}


SInput <- 20
KInput <- 25
Seq <- seq(from = KInput - 1, to = KInput + 1, by = 0.25)

C <- someFunction(
  S = SInput,
  K = Seq,                                                  
  type = "C"
)

P <- someFunction(
  S = SInput,
  K = Seq,
  type = "P"
)

df <- data.frame(C, P, Seq)         # create the data frame for the ggplot and Shiny output


df %>%                              # plot that data frame
  ggplot(aes(x = Seq)) +
  geom_line(aes(y = C)) +
  geom_line(aes(y = P))

I want to create the same ggplot - reactive plot in Shiny.我想在 Shiny 中创建相同的ggplot - 反应式 plot。 The Shiny code I have is the following.我拥有的 Shiny 代码如下。

library(shiny)
library(shinydashboard)

#######################################################################
############################### Functions #############################

someFunction <- function(S, K, type){
    
    # call option
    if(type=="C"){
        d1 <- S/K
        value <- S*pnorm(d1) - K*pnorm(d1)
        return(value)}
    
    # put option
    if(type=="P"){
        d1 <- S*K
        value <-  (K*pnorm(d1) - S*pnorm(d1))
        return(value)}
}


############################### Header ###############################
header <- dashboardHeader()

#######################################################################
############################### Sidebar ###############################
sidebar <- dashboardSidebar()

#######################################################################
############################### Body ##################################

body <- dashboardBody(
    fluidPage(
        numericInput("SInput", "Input S:", 10, min = 1, max = 100),
        numericInput("KInput", "Input K:", 10, min = 1, max = 100),
        tableOutput("S_K_Output")
    )
)

#######################################################################

ui <- dashboardPage(header, sidebar, body)

#######################################################################

server <- function(input, output) {
    output$S_K_Output <- renderTable({
        Seq <- seq(from = input$KInput - 1, to = input$KInput + 1, by = 0.25)    # create a sequence going from K-1 to K+1
        C <- someFunction(
            S = input$SInput,
            K = Seq,                                                    # Apply this sequence to the function
            type = "C"
        )
        P <- someFunction(
            S = input$SInput,
            K = Seq,
            type = "P"
        )
        data.frame(C, P, Seq)                                               # Extract the results and put side-by-side 
    })
}

shinyApp(ui, server)

The above Shiny code works for producing the table but I also want to include the plot.上面的 Shiny 代码适用于生成表格,但我还想包括 plot。 I am finding it difficult since the above code outputs the results into a renderTable({}) function (ie returning a HTML table and simply adding the ggplot code doesn't work.)我发现这很困难,因为上面的代码将结果输出到renderTable({}) function (即返回 HTML 表并简单地添加ggplot代码不起作用。)

I have tried renderPlot and pasting all the above code again from renderTable into the same function but I don't want to repeat unnecessary calculations.我已经尝试renderPlot并将上述所有代码再次从renderTable粘贴到同一个 function 但我不想重复不必要的计算。 So my question is how can I export the data.frame(C, P, Seq) into a ggplot2 graphic from two different renderTable and renderPlot ?所以我的问题是如何将data.frame(C, P, Seq)从两个不同的renderTablerenderPlot导出到ggplot2图形中? I can add the tablePlot just under the tableOutput in the fluidPage part of the code but I am not able to get results.我可以在代码的fluidPage部分的tablePlot下添加tableOutput ,但我无法获得结果。

Start thinking about dependency and removing redundancy.开始考虑依赖和消除冗余。 That is, if you are creating data of some sort and you even think that it will be used by more than one "thing", then break it out into "reactive data", and then depend on it in multiple locations.也就是说,如果您正在创建某种数据,并且您甚至认为它将被多个“事物”使用,那么将其分解为“反应性数据”,然后在多个位置依赖它。

Oh, and if you want to show a plot, you need to use plotOutput .哦,如果你想显示 plot,你需要使用plotOutput

Changes from your previous code:与您之前的代码相比的更改:

  • if you want a plot, you need to add a plotOutput ;如果你想要一个 plot,你需要添加一个plotOutput
  • convert the code in your renderTable into a reactive block that just calculates data , it does nothing to consider how to show or filter it;renderTable中的代码转换为只计算数据reactive块,它不考虑如何显示或过滤它;
  • re-add the renderTable to deal with the data as created in the previously-mentioned block;重新添加renderTable来处理前面提到的块中创建的数据;
  • add renderPlot (paired with plotOutput );添加renderPlot (与plotOutput配对); and finally最后
  • added req(mydata()) to the plot output, so that if the data is empty or NULL (for whatever reason), then the plotting code will not fire.req(mydata())添加到 plot output,这样如果数据为空或NULL (无论出于何种原因),则绘图代码将不会触发。 See ?req if you have questions about this, or its companion functions validate and need .如果您对此有疑问,请参阅?req ,或者它的配套函数validateneed

Note that when using reactive data, you must call it like a function.请注意,当使用响应式数据时,您必须像 function 一样调用它。 So the mydata reactive data block makes its data available to other reactive components when called as mydata() .因此,当调用mydata()时, mydata响应式数据块使其数据可用于其他响应式组件。 Do not try to "view" mydata (without the parens), it does nothing for you.不要试图“查看” mydata (没有括号),它对你没有任何作用。

library(shiny)
library(shinydashboard)

#######################################################################
############################### Functions #############################

someFunction <- function(S, K, type){
    
    # call option
    if(type=="C"){
        d1 <- S/K
        value <- S*pnorm(d1) - K*pnorm(d1)
        return(value)}
    
    # put option
    if(type=="P"){
        d1 <- S*K
        value <-  (K*pnorm(d1) - S*pnorm(d1))
        return(value)}
}


############################### Header ###############################
header <- dashboardHeader()

#######################################################################
############################### Sidebar ###############################
sidebar <- dashboardSidebar()

#######################################################################
############################### Body ##################################

body <- dashboardBody(
    fluidPage(
        numericInput("SInput", "Input S:", 10, min = 1, max = 100),
        numericInput("KInput", "Input K:", 10, min = 1, max = 100),
        tableOutput("S_K_Output"),
        plotOutput("Plot_Output")
    )
)

#######################################################################

ui <- dashboardPage(header, sidebar, body)

#######################################################################

server <- function(input, output) {
  mydata <- reactive({
    Seq <- seq(from = input$KInput - 1, to = input$KInput + 1, by = 0.25)    # create a sequence going from K-1 to K+1
    C <- someFunction(
      S = input$SInput,
      K = Seq,                                                    # Apply this sequence to the function
      type = "C"
    )
    P <- someFunction(
      S = input$SInput,
      K = Seq,
      type = "P"
    )
    data.frame(C, P, Seq)                                               # Extract the results and put side-by-side 
  })
  output$S_K_Output <- renderTable({ mydata() })
  output$Plot_Output <- renderPlot({
    req(mydata())
    # plot that data frame
    ggplot(mydata(), aes(x = Seq)) +
      geom_line(aes(y = C)) +
      geom_line(aes(y = P))
  })
}

shinyApp(ui, server)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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