2016-08-26 2 views
6

Ich versuche, eine kleine App zu schreiben, die es dem Benutzer ermöglicht, ein Streudiagramm zu erstellen, eine Teilmenge von Punkten im Diagramm auszuwählen und dann eine Tabelle im .csv-Format mit genau diesen ausgewählten Punkten auszugeben. Ich habe herausgefunden, wie man die Seite hochfährt und wie man mit brushedPoints Punkte auswählt. Die Tabelle mit ausgewählten Punkten wird angezeigt, aber wenn ich die Download-Schaltfläche drücke, ist der Fehler "Objekte von shinyoutput Objekt nicht lesen erlaubt." erscheint. Kann ich die Tabelle, die ich visuell als .csv auf dem Bildschirm sehen kann, nicht herunterladen? Wenn ja, gibt es einen Workaround?Lesen von Objekten vom glänzenden Ausgabeobjekt nicht erlaubt?

Ich habe das Problem mit dem Iris-Datensatz unten erstellt. Jede Hilfe, die herausfindet, warum ich die Tabelle der angezeigten Reihen nicht herunterladen kann, würde sehr geschätzt werden.

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) 

Antwort

10

Das Problem ist, dass das Ausgabeobjekt auch alle Web-Display-Sachen erzeugt. Stattdessen müssen Sie die Daten separat für den Download abrufen. Sie könnten es mit einem zweiten Aufruf an brushedPoints im Download-Code tun. Besser ist es jedoch, eine reactive() Funktion zu verwenden, um es nur einmal zu tun, dann rufen Sie das überall an, wo Sie es brauchen. Hier ist, wie ich Ihren Code ändern würde, um diese Arbeit zu machen.

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) 

(Beachten Sie, mit ggplot2, die Sie nicht explizit festlegen müssen xvar und yvar in brushedPoints So entfernte ich es hier erhöhen die Flexibilität der der Code.)

Ich bin nicht bewusst von "Lasso" Stil freie Zeichenfähigkeit in shiny (obwohl, geben Sie es eine Woche - sie fügen ständig Spaß Werkzeuge). Sie können das Verhalten jedoch nachahmen, indem Sie dem Benutzer erlauben, mehrere Regionen auszuwählen und/oder auf einzelne Punkte zu klicken. Die Serverlogik wird viel unordentlicher, da Sie die Ergebnisse in einem reactiveValues Objekt speichern müssen, um es wiederholt verwenden zu können. Ich habe etwas Ähnliches gemacht, um mir zu ermöglichen, Punkte auf einem Plot auszuwählen und sie auf anderen Plots zu markieren/zu entfernen. Das ist komplizierter als das, was Sie hier brauchen, aber das Folgende sollte funktionieren. Vielleicht möchten Sie andere Tasten/Logik hinzufügen (z. B. um die Auswahl "zurückzusetzen"), aber ich glaube, das sollte funktionieren. Ich habe eine Anzeige der Auswahl hinzugefügt, damit Sie verfolgen können, was ausgewählt wurde.

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) 
+0

Mark, das hat perfekt funktioniert! Die reaktive Funktion ist besonders hilfreich, danke, um mich darauf aufmerksam zu machen. Vielen Dank. – KrisF

+0

Mark, es ist mir aufgefallen, dass die Option brushedPoints nur dem Benutzer erlaubt, Punkte innerhalb eines Rechtecks ​​auszuwählen. Ist eine "Lasso" -Option möglich? Ich suchte herum, konnte aber in Plot.ly nur die "Lasso" -Option finden, die eine große Umschrift des obigen Skripts erfordern würde. – KrisF

+0

Nicht direkt, das ist mir bewusst. Allerdings habe ich nur eine Änderung hinzugefügt, die zeigt, wie man mehrere Auswahlen macht - das kann am Ende dasselbe Verhalten ergeben. –

Verwandte Themen