Rs200000000000
W aplikacji shiny (by RStudio), po stronie serwera, mam reactive, który zwraca listę zmiennych analizując zawartość textInput
. Lista zmiennych jest następnie używana w selectInput
i / lub updateSelectInput
.
outVar
bezpośrednio do selectInput
. Drugim podejściem jest użycie reaktywnego outVar
w updateSelectInput
. Ani działa.
Serwer.R
shinyServer(
function(input, output, session) {
outVar <- reactive({
vars <- all.vars(parse(text=input$inBody))
vars <- as.list(vars)
return(vars)
})
output$inBody <- renderUI({
textInput(inputId = "inBody", label = h4("Enter a function:"), value = "a+b+c")
})
output$inVar <- renderUI({ ## works but the choices are non-reactive
selectInput(inputId = "inVar", label = h4("Select variables:"), choices = list("a","b"))
})
observe({ ## doesn't work
choices <- outVar()
updateSelectInput(session = session, inputId = "inVar", choices = choices)
})
})
Ui.R
shinyUI(
basicPage(
uiOutput("inBody"),
uiOutput("inVar")
)
)
Jakiś czas temu, zamieściłem to samo pytanie na shiny-discuss, ale wzbudziło to małe zainteresowanie, więc pytam ponownie, z przeprosinami, https://groups.google.com/forum/#! topic/shiny-discuss / e0MgmMskfWo
Edit 1
@ Ramnath uprzejmie opublikował rozwiązanie, które wydaje się działać, oznaczone Edit 2 przez niego. Ale to rozwiązanie nie rozwiązuje problemu, ponieważ textinput
jest po stronie ui
zamiast po stronie server
Jak to jest w moim problemie. Jeśli przeniosę textinput
drugiej edycji Ramnatha na stronę server
, problem pojawi się ponownie, a mianowicie: nic się nie pokazuje i RStudio się zawiesza. Okazało się, że owinięcie input$text
w {[21] } sprawia, że problem znika.
Edit 2
W dalszej dyskusji Ramnath pokazał mi, że problem pojawia się, gdy serwer próbuje zastosować funkcję dynamiczną outVar
zanim jej argumenty zostaną zwrócone przez textinput
. Rozwiązaniem jest najpierw sprawdzenie, czy is.null(input$inBody)
istnieje.
sprawdzanie istnienia argumentów jest kluczowym aspektem budowania błyszczącej aplikacji, więc dlaczego o tym nie pomyślałem? Tak, ale musiałem zrobić coś złego! Biorąc pod uwagę ilość czasu, jaki spędziłem na problemie, jest to gorzkie doświadczenie. Pokazuję po kodzie, jak sprawdzić istnienie.
Poniżej znajduje się kod Ramnatha z textinput
przeniesiony na stronę server
. Wywala RStudio więc nie próbuj to w domu. (Użyłem jego notacji)
library(shiny)
runApp(list(
ui = bootstrapPage(
uiOutput('textbox'), ## moving Ramnath's textinput to the server side
uiOutput('variables')
),
server = function(input, output){
outVar <- reactive({
vars <- all.vars(parse(text = input$text)) ## existence check needed here to prevent a crash
vars <- as.list(vars)
return(vars)
})
output$textbox = renderUI({
textInput("text", "Enter Formula", "a=b+c")
})
output$variables = renderUI({
selectInput('variables2', 'Variables', outVar())
})
}
))
Sposób, w jaki zwykle sprawdzam istnienie, wygląda tak:
if (is.null(input$text) || is.na(input$text)){
return()
} else {
vars <- all.vars(parse(text = input$text))
return(vars)
}
Kod Ramnatha jest krótszy:
if (!is.null(mytext)){
mytext = input$text
vars <- all.vars(parse(text = mytext))
return(vars)
}
Oba wydają się działać, ale będę to robić po swojemu: może niezrównoważony wspornik w mojej konstrukcji wcześniej uniemożliwił mi wykonanie czeku? Czek ramnatha jest bardziej bezpośredni.
Na koniec chciałbym zwrócić uwagę na kilka rzeczy o moich różnych próbach debugowania.
W moim debugowaniu quest, odkryłem, że istnieje opcja "rangi" priorytetu "wyjść" po stronie serwera, które zbadałem próbując rozwiązać mój problem, ale nie zadziałało, ponieważ problem był gdzie indziej. Mimo to, jest to interesujące wiedzieć i wydaje się nie bardzo dobrze znane w tym czasie:
outputOptions(output, "textbox", priority = 1)
outputOptions(output, "variables", priority = 2)
W tej misji, ja również próbowałem try
:
try(vars <- all.vars(parse(text = input$text)))
Było blisko, ale nie udało się tego naprawić.
Pierwsze rozwiązanie, na które natknąłem się było:
vars <- all.vars(parse(text = as.character(input$text)))
Przypuszczam, że interesujące byłoby wiedzieć, dlaczego to działało: czy to dlatego, że spowalnia wszystko wystarczająco? czy to dlatego, że as.character
"czeka" na input$text
, aby być nie-null?
3 answers
Musisz użyć renderUI
Po stronie serwera dla dynamicznych interfejsów użytkownika. Oto minimalny przykład. Zwróć uwagę, że drugie rozwijane menu jest reaktywne i dostosowuje się do zestawu danych wybranego w pierwszym. Kod powinien być zrozumiały, jeśli wcześniej miałeś do czynienia z błyszczącym.
runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
uiOutput('columns')
),
server = function(input, output){
output$columns = renderUI({
mydata = get(input$dataset)
selectInput('columns2', 'Columns', names(mydata))
})
}
))
EDIT. Inne rozwiązanie za pomocą updateSelectInput
runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
selectInput('columns', 'Columns', "")
),
server = function(input, output, session){
outVar = reactive({
mydata = get(input$dataset)
names(mydata)
})
observe({
updateSelectInput(session, "columns",
choices = outVar()
)})
}
))
EDIT2: zmodyfikowany przykład za pomocą parse
. W tej aplikacji wprowadzona formuła tekstowa służy do dynamicznego wypełniania rozwijanego menu poniżej listą zmienne.
library(shiny)
runApp(list(
ui = bootstrapPage(
textInput("text", "Enter Formula", "a=b+c"),
uiOutput('variables')
),
server = function(input, output){
outVar <- reactive({
vars <- all.vars(parse(text = input$text))
vars <- as.list(vars)
return(vars)
})
output$variables = renderUI({
selectInput('variables2', 'Variables', outVar())
})
}
))
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-31 16:06:43
Z tego co wiem, problem polega na tym, że input$inBody
nie pobiera character
, nawet jeśli selectInput
funkcja otrzymuje character
jako wartość, czyli value = "a+b+c"
. Rozwiązaniem jest zatem zawinięcie input$inBody
w as.character
Następujące dzieła:
Podejście observe
z updateSelectInput
:
observe({
input$inBody
vars <- all.vars(parse(text=as.character(input$inBody)))
vars <- as.list(vars)
updateSelectInput(session = session, inputId = "inVar", choices = vars)
})
Podejście reactive
z selectInput
:
outVar <- reactive({
vars <- all.vars(parse(text=as.character(input$inBody)))
vars <- as.list(vars)
return(vars)
})
output$inVar2 <- renderUI({
selectInput(inputId = "inVar2", label = h4("Select:"), choices = outVar())
})
Edit: edytowałem moje pytanie z wyjaśnieniem na podstawie opinii Ramnatha. Ramnath wyjaśnił problem i dostarczył lepsze rozwiązanie, które daję jako edycję mojego pytania. Zatrzymam tę odpowiedź, ale nie zasługuje na głosy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-02 07:05:15
Serwer.R
### This will create the dynamic dropdown list ###
output$carControls <- renderUI({
selectInput("cars", "Choose cars", rownames(mtcars))
})
## End dynamic drop down list ###
## Display selected results ##
txt <- reactive({ input$cars })
output$selectedText <- renderText({ paste("you selected: ", txt() ,sep="") })
## End Display selected results ##
Ui.R
uiOutput("carControls"),
br(),
textOutput("selectedText")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 03:00:01