Shiny - assistance passing a local variable generated by radio fr0om UI to server

,

Question for those who are more versed in shiny than I am... How do I pass the value of temp created locally under UI, to put in the subset function inside Server. I have reviewed reactive and observe, however not versed enough yet to resolve. Basically I want it so that if I click various radio buttons, then the application will change the graphics I generate based on the new subset of data drawn. I know the operation of my app works as if I substitute "hrdcoffice == 1194001", it works, just not the reference using temp, ie "hrdcoffice == temp"

Code below:

ui = fluidPage(

  tabsetPanel(

############################ Tab 1 Layout ########################

    tabPanel("Respondents Profile", fluid = TRUE,
           sidebarLayout(sidebarPanel("Control Panel", 
                             helpText("Results of survey from 01/01/2019 to 04/17/2024"),
                             tags$style(type='text/css', ".selectize-input { font-size: 10px; line-height: 10px;} .selectize-dropdown { font-size: 10px; line-height: 10px; }"),
                             position = "right",
                             radioButtons ("loc", "What community do you want to view?", 
                                           choices = c("Place A", "Place B"
                                           ),
                                           
                                           selected = "Place B"),
                             style="font-size:11px"),
 
           mainPanel(
           #Suevey
           #Age at Survey
           card(
             height ="400px",

               splitLayout(cellWidths = c("50%", "50%"), plotOutput("Survey_Version",  width = "100%",  height = "100%"), plotOutput("Age",  width = "100%",  height = "100%"))
           ),
           
           
           textOutput("location"),

           conditionalPanel(condition = "input.loc == 'Place A'", temp <- 1192004),
           conditionalPanel(condition = "input.loc == 'Place B'", temp <- 1194001),
          
           textOutput("samplesize")
           ))

)

))

Define server logic ----

server <- function(input, output) {
comm <- read_sav("C:/Users/ACollier/Documents/R_Projects/IRResources/reduced.sav")

DF  <- as.data.frame(subset(comm, hrdcoffice == temp))



...
...

Run the app ----

shinyApp(ui = ui, server = server)

In your radioButtons, swap

for

choices = c("Place A" = 1192004, "Place B" = 1194001)

This will display "Place X" in the UI but return the value of 119xxxx when input$loc is called in the server.

Drop both conditionalPanels - that's not what these are for. Use conditionalPanel to selectively show sections of UI elements based on the value of inputs, not for setting values.

In server:

DF <- reactive({
  as.data.frame(subset(comm, hrdcoffice == input$loc))
})

# Recall the value of DF using DF(), e.g.
output$samplesize <- renderText(nrow(DF()))

It doesn't seem to like the

DF <- reactive({
as.data.frame(subset(comm, hrdcoffice == input$loc))

})

Warning: Error in .getReactiveEnvironment()$currentContext: Operation not allowed without an active reactive context.
• You tried to do something that can only be done from inside a reactive consumer.
47:
46: signalCondition
45: signal_abort
44: rlang::abort
43: .getReactiveEnvironment()$currentContext
42: getCurrentContext
41: .dependents$register
40: community1
38: server [C:\Users\ACollier\Documents\App-1/app.R#352]
1: runApp
Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context.
• You tried to do something that can only be done from inside a reactive consumer.

I have changed the name from DF to community1, as it first told me i was passing a function in ggplot... as df() is a function... so it now looks like
sversion <- ggplot(data = community1(), aes(survey_version)) ....
for example

I have tried other combinations of putting reactive in front of various pieces of the dataframe command, but to no avail... would it be that I am trying to be reactive on a dataframe?

please format your code ( and error messages) ; the 6th button in this forums ui is a helper for that.
you can also launch it with CTRL+E on keyboard

type or paste code here

a reactive context means within the body {} of either a reactive()/observe()/render*() function or equivalent. if you are accessing community1() outside of one of those, you get your error.

1 Like

This is the error message you get if you try to call a reactive value (DF()) outside of a reactive or render object.

Can you confirm you left the DF <- reactive({...}) code inside of the

server <- function(input, output) {
  ...
}

function and that all attempts to call DF() or community1() happen inside render*() or reactive() functions?

It should have this outline:

server <- function(input, output) {
  # ... other server code ...

  DF <- reactive({
    as.data.frame(subset(comm, hrdcoffice == input$loc))
  })

  # Recall the value of DF using DF(), e.g.
  output$samplesize <- renderText(nrow(DF()))

  ## ... other server code...
}

#All the following are inside server component as you specified. All of my output appear as so... my ggplot is outside... as per your note, maybe should go inside the render, however if I put inside, it throws up a "Error in : x and y must have same types and lengths." error... that did not seem to be an issue before... know it is a ripple effect :slight_smile:

#Survey Year        
surveyyear <- ggplot(data = community1(), aes(Survey_Year)) + geom_text(stat="count", aes(label = ..count..),vjust = -.7) + geom_histogram(binwidth = .5, fill = "#C7CDC6", color = "#A2574D")
 
output$Survey_Year <- renderPlot({
  surveyyear <- ggplot(data = community1(), aes(Survey_Year)) + geom_text(stat="count", aes(label = ..count..),vjust = -.7) + geom_histogram(binwidth = .5, fill = "#C7CDC6", color = "#A2574D")
  surveyyear  <- surveyyear  + scale_x_continuous(breaks=c(2018, 2019, 2020, 2021, 2022, 2023, 2024),labels = c("2018", "2019", "2020", "2021", "2022", "2023", "2024"),guide=guide_axis(angle = 45),limits = c(2017,2025)) + labs(x = "Survey Years") + labs(title = "Survey Years", subtitle = "Frequency")
  surveyyear  <- surveyyear + labs(caption = "(From March 31, 2024 Data Survey)")
  
  surveyyear
}, height = 400, width = 400) 

they feed a card in the UI such as :
card(
height ="400px",

               splitLayout(cellWidths = c("50%", "50%"), plotOutput("Survey_Version",  width = "100%",  height = "100%"), plotOutput("Age",  width = "100%",  height = "100%"))
           ),

Yes, I think that is where my error was, had command outside the render referencing the dataframe... still navigating the controls on this forum stuff yet... will get there ... i will keep the training wheel for now though lol... thank you!

Still have this error with a simple reference to reactive with dataframe, and simple output text call ... even took out the as.data.frame command, ... what are the x and y they are referencing?

what are the x and y they are referencing?

I don't have enough information to diagnose this. We would need to see any stack trace associated with that error message or a reproducible example (code and data) to know what part is causing this issue. Could you provide more information?

An excerpt from the app, followed by the stack dump

# Load packages

library(shiny)
#library(shinyjs)
library(bslib)
library(ggplot2)
library(magrittr)
library(lubridate)
library(foreign)
library(dplyr)
library(DT)
library(bsicons)
library(haven)
library(ggplot2)
library(plotly)



ui = fluidPage(
  
  tabsetPanel(
    
    
    ############################ Tab 1 Layout ########################  
    
    tabPanel("Respondents Profile", fluid = TRUE,
             sidebarLayout(sidebarPanel("Control Panel", 
                                        helpText("Results of survey from 01/01/2019 to 04/17/2024"),
                                        tags$style(type='text/css', ".selectize-input { font-size: 10px; line-height: 10px;} .selectize-dropdown { font-size: 10px; line-height: 10px; }"),
                                        position = "right",
                                        radioButtons ("loc", "What community do you want to view?", 
                                                      choices = c("Place A" = 1122000,
                                                                  "Place B" = 1130001
                                                                  
                                                      ),
                                                      
                                                      selected = "Place A"),
                                        style="font-size:11px"),
                           
                           mainPanel(
                             #Sample
                             #Age at Survey
                             # card(
                             #   height ="400px",
                             #   
                             #   splitLayout(cellWidths = c("50%", "50%"), plotOutput("Survey_Version",  width = "100%",  height = "100%"), plotOutput("Age",  width = "100%",  height = "100%"))
                             # ),
                             # 
                             # textOutput("location"),
                             textOutput("samplesize")
                           ))
             
             
             
    )     
    
    
    
  )
)





# Define server logic ----
server <- function(input, output) {
  comm <- read_sav("C:/Users/ACollier/Documents/R_Projects/IRResources/reduced.sav")
  
  community1 <- reactive({
    as.data.frame(subset(comm, hrdcoffice == input$loc))
  })
  
  
  
  ############################Server stuff for Tab 1 ########################
  #Survey Verison 
  
  
  # output$Survey_Version <- renderPlot({
  #   sversion <- ggplot(data = community1(), aes(survey_version)) + geom_text(stat="count", aes(label = ..count..),vjust = -0.7) + geom_histogram(binwidth = 0.5,   fill = "#757575", color = "#1A381B")
  #   sversion <- sversion + scale_x_continuous(breaks=c(1, 2, 3),labels = c("Version 1", "Version 2", "Version 3")) + labs(x = "Survey Version") + labs(title = "Survey Version", subtitle = "Frequency")
  #   sversion <- sversion + labs(caption = "(From March 31, 2024 Data Survey)")
  #   
  #   sversion
  # }, height = 400, width = 400)
  # 
  # 
  # #Age Output
  # output$Age <- renderPlot({
  #   age <- ggplot(data = community1(), aes(factor(r_Age_at_survey))) + geom_bar(width = 0.1) + geom_text(stat="count", aes(label = ..count..),vjust = -.7) + geom_histogram(stat="count",fill = "#99846D",color = "#1A381B")
  #   age <- age  + labs(x = "Age at Survey") + labs(title = "Age at Survey", subtitle = "Frequency")
  #   age <- age + scale_x_discrete(breaks = c(19, 29, 44, 54, 64, 65),labels = c("Under 20", "20 to 29", "30 to 44", "45 to 54", "55 to 64", "65 Plus"),guide=guide_axis(angle = 45)) + labs(caption = "(From March 31, 2024 Data Survey)")
  #   
  #   age
  # }, height = 450, width = 450)
  # 
  
  # Recall the value of community1 using community1(), e.g.
  output$samplesize <- renderText(nrow(community1()))
  
  
}

# Run the app ----
shinyApp(ui = ui, server = server)

Warning: Error in : x and y must have same types and lengths.
122: vec_equal
121: ==.vctrs_vctr
120: eval
119: eval
118: subset.data.frame
115: reactive:community1 [C:\Users\ACollier\Documents\App-1/app.R#71]
99: community1
97: renderText
96: func
83: renderFunc
82: output$samplesize
1: runApp
Warning: Error in vec_equal: Can't combine ..1 and ..2 .
142:
141: signalCondition
140: signal_abort
139: abort
138: stop_vctrs
137: stop_incompatible
136: stop_incompatible_type
132: vec_default_ptype2
131:
130: vec_ptype2
129: vec_ptype2.character.haven_labelled
128:
127: vec_ptype2
126: vec_ptype2.haven_labelled.character
125:
124: vec_cast_common_opts
123: vec_cast_common_params
122: vec_equal
121: ==.vctrs_vctr
120: eval
119: eval
118: subset.data.frame
115: reactive:community1 [C:\Users\ACollier\Documents\App-1/app.R#71]
99: community1
97: renderText
96: func
83: renderFunc
82: output$samplesize
1: runApp
Warning: Error in vec_equal: Can't combine ..1 and ..2 .
142:
141: signalCondition
140: signal_abort
139: abort
138: stop_vctrs
137: stop_incompatible
136: stop_incompatible_type
132: vec_default_ptype2
131:
130: vec_ptype2
129: vec_ptype2.character.haven_labelled
128:
127: vec_ptype2
126: vec_ptype2.haven_labelled.character
125:
124: vec_cast_common_opts
123: vec_cast_common_params
122: vec_equal
121: ==.vctrs_vctr
120: eval
119: eval
118: subset.data.frame
115: reactive:community1 [C:\Users\ACollier\Documents\App-1/app.R#71]
99: community1
97: renderText
96: func
83: renderFunc
82: output$samplesize
1: runApp
Warning: Error in vec_equal: Can't combine ..1 and ..2 .
142:
141: signalCondition
140: signal_abort
139: abort
138: stop_vctrs
137: stop_incompatible
136: stop_incompatible_type
132: vec_default_ptype2
131:
130: vec_ptype2
129: vec_ptype2.character.haven_labelled
128:
127: vec_ptype2
126: vec_ptype2.haven_labelled.character
125:
124: vec_cast_common_opts
123: vec_cast_common_params
122: vec_equal
121: ==.vctrs_vctr
120: eval
119: eval
118: subset.data.frame
115: reactive:community1 [C:\Users\ACollier\Documents\App-1/app.R#71]
99: community1
97: renderText
96: func
83: renderFunc
82: output$samplesize
1: runApp

your error might be a result of mistmatched types here.
the type of input$loc is character I would assume
is hrdoffice a string also ? or might if be a factor ? or potentially if its coming from haven::read_sav could it be a in fact a double with associated labels ?

hrdcoffice is numeric... where I never put quotes around the string 1194001 in the definition, I assumed it was still numeric... would input$loc change it to string? or asked another way, does the type change when using this reference?

input$loc will have converted to character. Convert it back to numeric using as.numeric(input$loc)

the radioButtons server code determines the type, and it always returns character. This is documented in the radioButtons help. as keithn, its trivial to cast the result to the numeric that you need.

I am going in baby steps now... Yes, decided to make whatever I could explicit with types I needed, so making it numeric would force it to the required format... It will produce the desired output of the number of rows in the dataframe in the simple example but I get a stack dump... I am thinking it doesn't like the dataframe input format or same,,, what I might have to do is instead of reading in the data frame, maybe reference a variable at a time? tackle the dump before going further... less intuitive than old school programming :slight_smile:

Warning: Error in vec_equal: Can't recycle `..1` (size 34920) to match `..2` (size 0).
  130: <Anonymous>
  129: signalCondition
  128: signal_abort
  127: abort
  126: stop_vctrs
  125: stop_incompatible
  124: stop_incompatible_size
  123: vec_recycle_common
  122: vec_equal
  121: ==.vctrs_vctr
  120: eval
  119: eval
  118: subset.data.frame
  115: <reactive:community1> [C:\Users\ACollier\Documents\App-1/app.R#204]
   99: community1
   97: renderText
   96: func
   83: renderFunc
   82: output$samplesize
    1: shiny::runApp

You havent guarded for the possibility that input$loc could be uninitialised and its value numeric(0);
shiny provides req() for that reason.

DF <- reactive({
  as.data.frame(subset(comm, hrdcoffice == req(input$loc)))  # <--- using req() on input
})
1 Like

I had used "selected" in my UI as a default value but never passed using $... something so simple... thank you so much!!! It got me past a huge hurdle!!!