2
votes

I have a data frame that combines sociodemographic data with Awareness Measues for multiple Websites. Each website has a separate column stating if the person knows the website ("Yes"/"No"). Furthermore, each interviewee should be weighted by the number of people he presents (variable popWeight).

I want to create a shiny app that shows plots for people that are aware of a selected Website. The website should be selectable by a selectInput () Button.

I found a couple of articles on stackoverflow that cover dataset filters with dplyr+shiny. But all of them vary the variable value rather than the variable itself.

I tried to work with the following, but to no success (Coding example see below).

[Use shiny text input and dplyr to filter rows in a dataframe

Sample Data Frame:

gender <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Male", "Female", "Missing Value"))
age <- sample(18:55, 5, replace=TRUE)
web1 <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Yes", "No", "Missing Value"))
web2 <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Yes", "No", "Missing Value"))
web3 <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Yes", "No", "Missing Value"))
web4 <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Yes", "No", "Missing Value"))
web5 <- factor(sample(1:2, 5, replace=TRUE), levels = c(1,2,99), labels = c("Yes", "No", "Missing Value"))
popWeight <- sample(1000:1500, 5, replace=TRUE)

df <- data.frame(gender, age, web1, web2, web3, web4, web5, popWeight)
df

What I want to do in an interactive way:

library(ggplot2)
library(dplyr)

df1 <- filter (df, web1 == "Yes")

ggplot(df1)+
  aes(x=gender, y=popWeight/sum(popWeight))+
  stat_summary(fun.y = sum, geom = "bar")+
  scale_y_continuous("Population (%)", labels = scales::percent)

What I tried

library(shiny)
library(ggplot2)
library(dplyr)

ui <- fluidPage(
  selectInput(inputId = "WebsiteName", label = "Choose a Website", choices = names(df) [c(3:7)]),
  plotOutput("Gender")
)


server <- function(input, output) {

  dfInput <- reactive({
    df %>% filter (input$WebsiteName == "Yes")
  })

  output$Gender <- renderPlot({
    df1 <- dfInput()
    ggplot(df1)+
      aes(x=gender, y=popWeight/sum(popWeight))+
      stat_summary(fun.y = sum, geom = "bar")+
      scale_y_continuous("Population (%)", labels = scales::percent)
  })
}


shinyApp(ui = ui, server = server)

Is there a way how I can vary the filter variable rather than the value? I'm also open for other solutions.

2

2 Answers

0
votes

I think you need to add a second UI that depends on the variable selected on the first. Here, I've created it in the server with renderUI(). I then subset the data using that column selected being equal to the variable selected. Hope this helps.

library(shiny)
library(ggplot2)
library(dplyr)

ui <- fluidPage(
  selectInput(inputId = "WebsiteName", label = "Choose a Website", choices = names(df) [c(3:7)]),
  htmlOutput("variableUI"),
  plotOutput("Gender")
)


server <- function(input, output) {

  output$variableUI <- renderUI({
    selectInput(inputId = "variable", label = "Choices", choices = df[,input$WebsiteName])
  })

  dfInput <- reactive({
   ##subsetting is a bit tricky here to id the column on which to subset        
    df[ df[ , input$WebsiteName ] == input$variable, ]
  })

  output$Gender <- renderPlot({
    df1 <- dfInput()
    ggplot(df1)+
      aes(x=gender, y=popWeight/sum(popWeight))+
      stat_summary(fun.y = sum, geom = "bar")+
      scale_y_continuous("Population (%)", labels = scales::percent)
  })
}


shinyApp(ui = ui, server = server)
5
votes

You can tidy you dataset to transform it in a more usable way and save yourself some headaches:

Tidy dataset

df<- df %>% 
    gather(web, value, -age, -gender, -popWeight)

UI

Changed the selectInput choices

ui <- fluidPage(
  selectInput(inputId = "websiteName", 
              label = "Choose a Website", 
              choices = unique(df$web)),
  plotOutput("Gender")
)

SERVER

Updated the reactive expression

server <- function(input, output) {

  dfInput <- reactive({
    df %>% filter(web == input$websiteName & value == "Yes")
  })

  output$Gender <- renderPlot({
    df1 <- dfInput()
    ggplot(df1) +
      aes(x = gender, y = popWeight / sum(popWeight)) +
      stat_summary(fun.y = sum, geom = "bar") +
      scale_y_continuous("Population (%)", labels = scales::percent)
  })
}