Ich arbeite an einer Shiny-Anwendung, in der zwei Schieberegler-Eingänge vorhanden sind. Diese eingegebenen Werte unterteilen ein Datenframe unterschiedlich und die Teilmenge dieses Datenframes wird dann in ein Streudiagramm geplottet.Das Objekt wurde nicht gefunden, wenn es aus der Funktion isolate() in Shiny erstellt wurde.
Ich versuche zu verhindern, dass das Scatterplot neu plottiert wird, es sei denn, der Benutzer klickt auf ein "Go!" Taste. Um dies zu erreichen, verwende ich die Funktion isolate() auf den Schieberegler-Eingabewerten, so dass der Datenrahmen und das Diagramm nur aktualisiert werden, wenn das "Go!" Schaltfläche wird geändert.
Das scheint in Ordnung zu sein, aber ich versuche auch, dem Benutzer zu ermöglichen, das Auswahlwerkzeug in Plotly zu verwenden und die Datenrahmenzeilen zu sehen, die dieser Auswahl entsprechen. Wenn ich dies jedoch versuche, erhalte ich einen Fehler ("Fehler: Objekt 'datInput' nicht gefunden"). Diese Zeile ist im folgenden Beispiel kommentiert:
library(shiny)
library(plotly)
ui <- shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
sliderInput("val1", "Value 1:", min = 0, max = 1, value=0.5, step=0.1),
sliderInput("val2", "Value 2:", min = 0, max = 1, value=0.5, step=0.1),
actionButton("goButton", "Go!")
),
mainPanel(
plotlyOutput("plot1"),
verbatimTextOutput("click")
)
))
server <- shinyServer(function(input, output) {
set.seed(1)
dat <- data.frame(Case = paste0("case",1:15), val1=runif(15,0,1), val2=runif(15,0,1))
dat$Case <- as.character(dat$Case)
xMax = max(dat$val1)
xMin = min(dat$val1)
yMax = max(dat$val2)
yMin = min(dat$val2)
maxTemp = max(abs(xMax), abs(xMin))
observeEvent(input$goButton,
output$plot1 <- renderPlotly({
# Use isolate() to avoid dependency on input$val1 and input$val2
datInput <- isolate(subset(dat, val1 > input$val1 & val2 > input$val2))
p <- qplot(datInput$val1, datInput$val2) +xlim(0, ceiling(maxTemp)) +ylim(0,1)
ggplotly(p)
})
)
d <- reactive(event_data("plotly_selected"))
output$click <- renderPrint({
if (is.null(d())){
"Click on a state to view event data"
}
else{
#str(d()$pointNumber) #Seems to be working
datInput[d()$pointNumber,] #Error: object 'datInput' not found
}
})
})
shinyApp(ui, server)
Alle Ideen für eine Problemumgehung für dieses Problem würden wir uns freuen!
EDIT:
Hier ist die Lösung gemäß @mlegge. Ich habe einfach die Ausgabe, nachdem der Benutzer bestimmte Punkte auswählt:
library(shiny)
library(plotly)
ui <- shinyUI(pageWithSidebar(
headerPanel("Click the button"),
sidebarPanel(
sliderInput("val1", "Value 1:", min = 0, max = 1, value=0.5, step=0.1),
sliderInput("val2", "Value 2:", min = 0, max = 1, value=0.5, step=0.1),
actionButton("goButton", "Go!")
),
mainPanel(
plotlyOutput("plot1"),
verbatimTextOutput("click")
)
))
set.seed(1)
dat <- data.frame(Case = paste0("case",1:15), val1=runif(15,0,1), val2=runif(15,0,1))
dat$Case <- as.character(dat$Case)
xMax = max(dat$val1)
xMin = min(dat$val1)
yMax = max(dat$val2)
yMin = min(dat$val2)
maxTemp = max(abs(xMax), abs(xMin))
server <- shinyServer(function(input, output) {
# datInput only validated once the go button is clicked
datInput <- eventReactive(input$goButton, {
subset(dat, val1 > input$val1 & val2 > input$val2)
})
output$plot1 <- renderPlotly({
# will wait to render until datInput is validated
plot_dat <- datInput()
p <- qplot(plot_dat$val1, plot_dat$val2) + xlim(0, ceiling(maxTemp)) +ylim(0,1)
ggplotly(p)
})
d <- reactive(event_data("plotly_selected"))
output$click <- renderPrint({
if (is.null(d())){
"Click on a state to view event data"
}
else{
#str(d()$pointNumber)
datInput()[d()$pointNumber+1,] #Working now
}
})
})
shinyApp(ui, server)
Vielen Dank für die hilfreiche Antwort! Könnten Sie bitte erklären "Sie werden feststellen, dass Ihre Datengenerierung außerhalb des Servers verschoben wurde, weil sie nur einmal ausgeführt werden muss." Wie könnte ich das wissen, und hat das irgendwelche Nachteile? Insbesondere macht das Generieren von Daten außerhalb des Servers es für große Datasets langsamer (wofür ich als mein Ziel arbeite!) Danke. – LanneR
Der 'Server' wird jedes Mal ausgeführt, wenn etwas ungültig gemacht wird, also lade/erzeuge immer große Datenmengen in' global.R' (oder einfach in deiner Session, wenn du eine einzige 'app.R' ausführst) an vermeiden Sie, diesen großen Datenprozess immer und immer wieder zu haben. – mlegge
Hier ist, was ich spreche über https://shiny.rstudio.com/articles/scoping.html#objects-visible-across-all-sessions und https://shiny.rstudio.com/articles/scoping.html # global-objects – mlegge