2016-05-06 5 views
2

Ich schreibe eine glänzende App, in der eine stochastische Funktion enthält generiert vier Objekte - ein Diagramm und drei Tabellen. Ich möchte jedoch jedes Objekt in verschiedenen Registerkarten rendern, ohne die Funktion viermal auszuführen, da diese stochastische Funktion vier verschiedene Versionen generiert. Ich wurde online recherchiert und finde viele Leute, die "reactive()" empfehlen, aber ich verstehe immer noch nicht ganz, wie ich es auf mein Problem anwenden soll. Wie kann ich diese vier Objekte beim Rendern mit nur einer Ausführung der Funktion verwenden?Wie rendert man mehrere Ausgaben aus derselben Analyse, ohne sie mehrfach auszuführen? (Shiny)

Meine „server.R“ Struktur im Grunde wie die unten aussieht:

shinyServer(function(input, output) { 

    stochastic_function() { 
      ... 
     plot1 <- ... 
     table1 <- ... 
     table2 <- ... 
     table3 <- ... 
     result <- list(plot, table1, table2, table3) 
    return(result) 
    } 

output$plot <- renderPlot({ 

}) 

output$table1 <- renderTable({ 

}) 

output$table2 <- renderTable({ 

}) 

output$table3 <- renderTable({ 

}) 

... 

Also, ich habe für die stochastische Funktion so etwas wie unten versucht:

model <- eventReactive(input$goButton, { 
     reactive(WG_Model(cdata = cdata(), # load data from outside env 
          sdata = sdata(), # load data from outside env 
          N = input$n, 
          end_date = input$end_date, 
          cpx_goal = input$cpx, 
          N_new = input$n2, 
          end_date_new = input$end_date2, 
          spend_range = input$s_range, 
          spend_incr = input$s_incr 
         ) 
       ) 
}) 

Die Idee ist, ein hinzufügen "GoButton" um die Funktion zu starten und dann alle Ausgänge in einem reaktiven fun() zu speichern. So kann ich jeden Ausgang mit Render:

output$plot <- renderPlot({ 
    model$gplot 
}) 

output$table <- renderTable({ 
    model$table 
}) 

# Render UI section 
output$tb <- renderUI({ 
    tabsetPanel(tabPanel("About Model", plotOutput("plot")), 
       tabPanel("About Model", tableOutput("table"))) 

    }) 

aber ich bekam immer nur „Fehler: Objekte vom Typ‚Schließung‘ist nicht subsettable“ in der Benutzeroberfläche ausgegeben. Welchen Teil habe ich vermisst?

+0

Hey @warmoverflow :) Ich habe noch nichts versucht, aber ich denke mit "Modell <- reaktiv (function() {..})" alle Ausgänge in eine Liste zu speichern. Dann rendere jede Ausgabe mit Listenindexierung wie "render ... (model() $ plot)". Ich versuche es. –

+0

@warmoverflow Ich habe es getestet und habe eine Fehlermeldung erhalten. Ich habe den Beitrag mit dem Ergebnis aktualisiert. Bitte lassen Sie mich wissen, wenn Sie eine Idee haben. Danke! :) –

+0

In 'reactiveEvent' brauchst du nicht mehr' reactive'. 'model' sollte einen Wert zurückgeben, auf den Sie mit' model() 'zugreifen können. Sie haben vergessen, Klammern innerhalb Ihrer 'render *' - Funktionen hinzuzufügen. (es sollte 'model() $ table' sein) –

Antwort

3

Wenn Ihre model() eine Liste ist und Daten für alle Tabellen und ein Diagramm enthält, sollte es wie in meinem Beispiel funktionieren.

In dieser App werden nach dem Drücken einer Schaltfläche eine Zufallszahl und Daten für eine Tabelle und ein Diagramm generiert. Dann werden die Nummer, die Daten für die Tabelle und ein Plot als Liste zurückgegeben und mit den entsprechenden Funktionen render* gerendert.

Diese App zeigt an, dass die model-Funktion nach dem Zugriff mit model() in anderen reaktiven Funktionen nicht erneut ausgeführt wird.

Allerdings gibt es eine seltsame Sache ... die Handlung wird nicht immer gerendert. Manchmal müssen Sie mehrmals auf die Schaltfläche klicken, um das Diagramm zu erhalten. Der Tisch funktioniert immer.


library(shiny) 

ui <- shinyUI(fluidPage(
    br(), 
    actionButton("numb", "generate a random numbers"), 
    br(), 
    br(), 
    verbatimTextOutput("text"), 
    plotOutput("plot"), 
    tableOutput("table") 
)) 

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

    model <- eventReactive(input$numb, { 
    # draw a random number and print it 
    random <- sample(1:100, 1) 
    print(paste0("The number is: ", random)) 

    # generate data for a table and plot 
    data <- rnorm(10, mean = 100) 
    table <- matrix(data, ncol = 2) 

    # create a plot 
    Plot <- plot(1:length(data), data, pch = 16, xlab ="", ylab = "") 

    # return all object as a list 
    list(random = random, Plot = Plot, table = table) 
    }) 

    output$text <- renderText({ 
    # print the random number after accessing "model" with brackets. 
    # It doesn't re-run the function. 
    youget <- paste0("After using model()$random you get: ", model()$random, 
         ". Compare it with a value in the console") 
    print(youget) 
    youget 
    }) 

    output$plot <- renderPlot({ 
    # render saved plot 
    model()$Plot 
    }) 

    output$table <- renderTable({ 

    model()$table 
    }) 
}) 


shinyApp(ui = ui, server = server) 
+0

Ja! Es funktioniert perfekt! Danke für das Zusammenstellen aller Details! –

+0

Gut zu hören :) War die 'print'-Funktion die Ursache dafür, dass gg-plot nicht gerendert wurde? –

+1

Nein, es war nur ein kleiner Tippfehler.; P Danke! Oh, übrigens, eine kurze Frage, nur für den Fall, dass Sie die Antwort kennen - während Sie die Funktion model() ausführen, werden viele Protokollinformationen gedruckt, indem Sie "print (" xxx ")" in der Konsole verwenden. Gibt es eine Möglichkeit, diese "Print()" - Protokollinformationen auf der Benutzeroberfläche darzustellen? –

Verwandte Themen