Getting a new variable based on reactive shiny input value and established dataset (R)

37 Views Asked by At

I am new to R Shiny and am trying to attach a row value to a dataset based on the input value. Here is a cut-down example version. The UI has the user inputting their ZIP code and State

 ui = fluidPage(
    titlePanel("Avg Age"),
    sidebarLayout(position = "left",
                  sidebarPanel(
                    numericInput(inputId = 'zip', label = 'Zip Code', value = NA),
                    selectInput(inputId = 'state', label = 'State', choices = c('Arkansas','Connecticut','Georgia','Illinois','Indiana','Louisiana','Maine','Maryland','Massachusetts','Michigan', 'New Hampshire', 'New Jersey', 'New York', 'Ohio', 'Oklahoma', 'Pennsylvania', 'Tennesee','Virginia', 'Vermont', 'Wisconsin')),
                    numericInput(inputId = 'height', label = 'Height', value = 54),
                    submitButton('Calculate')
                  ),
                  mainPanel(
                    textOutput("Pred")),
                  )
  )

Then the server will use an established dataset in my Global Environment to pull a new variable, run it through the model and give an output.

 server = function(input,output) {
    
    CL <- CL23
    
    data <- reactive({
      data.frame(
        avg_age =ifelse(CL23$State == input$state & CL23$Zip == input$zip, CL23$Age, NA),
        state = input$state,
        zip_code = input$zip,
        height_input = input$height
      )
    })
    
    pred = reactive({predict(RefreshModel,data())})
    
    output$Pred <- renderPrint(pred())

  }
  

What the goal would be if the user inputs zip code as 12345 and state as Michigan, then it will look through my dataset CL23 that looks like below and grab the appropriate age value in the column. So in this case it would grab the value 23.

State Zip Age
Alabama 12456 55
Michigan 12345 23
Michigan 12444 72

Ideally I would want the data to have all the user input values but one additional row that has the Age value from the CL dataset.

I tried the way above and I got an error in my Shiny App when I click "calculate". I also tried calling upon it earlier in the server code with

agepart2 <- input %>% 
        inner_join(CL, by=c("zip"="Zip","state"="State")) 

and calling upon agepart2 in the data.frame stage but also got an error when running the app.

1

There are 1 best solutions below

0
Mark Alvares On

To get the corresponding age value you'll want to filter your data frame for the row that matches the input state and zip code, then pull out the age value. I've done this with dplyr but you can likely do it with base R if you wish:

server <- function(input,output) {
  
  CL <- tibble(State = c("Alabama", "Michigan", "Michigan"),
               Zip = c(12456, 12345, 12444),
               Age = c(55, 23, 72))
  
  
  data <- reactive({
    # Grabs the corresponding age value for the input state and zip values.
    # Will be NULL if there is no matching row in CL.
    corresp_age <- CL %>% 
      filter(State == input$state & Zip == input$zip) %>% 
      pull(Age)
    
    # Now we can create the dataframe, filling the age with NA if there
    # is no corresponding age.
    data.frame(
      avg_age = ifelse(is.null(corresp_age), NA, corresp_age),
      state = input$state,
      zip_code = input$zip,
      height_input = input$height
    )
  })

  # ...
}

You can now check that data() behaves as we want it to, e.g. by rendering it to the UI.

For reference, when including something like CL23$State == input$state in your condition for ifelse, you're comparing a vector with many values (the entire State column in CL23) to a single value (input$state), hence the error.