1

I am writing a Shiny app to create a row containing a table for each variable in a dataset. The number of variables will change from use to use, and ideally the app will output as many rows and tables as there are variables. My current code is creating the correct number of rows and text, but is repeating the table data for the last table for all rows. I believe that the storing of table outputs in output[[tablename]] may not be in the right place to create separately stored tables. The next step will be to add a reactive input to filter the rows shown by vardata$category.

  • What do I need to do to have the correct data populate for the table in each row?
  • What would I need to do to then filter which rows are shown with a reactive input?

Code here includes data example:

library(shiny)    
variable <- c("Q17r01", "Q17r01", "Q17r01", "Q22r03", "Q22r03", "Q22r03", "Q15r01", "Q15r01", "Q15r01", "S03", "S03", "vAge", "vAge", "vAge", "vAge", "vAge", "vAge")
    responses <- c("A_T", "B_M", "C_B", "A_T", "B_M", "C_B", "A_T", "B_M", "C_B", "Female", "Male", "13 - 17", "18 - 24", "25 - 34", "35 - 44", "45 - 54", "55+")
    grp1 <- c(33, 39, 28, 27, 20, 53, 88, 7, 5, 51, 49, 27, 8, 33, 14, 16, 2)
    grp2 <- c(42, 46, 12,41, 45, 13, 64, 32, 4, 44, 56, 9, 22, 39, 13, 12, 4)
    xAgg <- c(32, 49, 19, 26, 48, 26, 51, 38, 11, 45, 55, 12, 16, 30, 17, 14, 11)
    chartdata <- data.frame(variable,responses,grp1,grp2,xAgg,row.names=NULL)

    profvars <- unique(variable)
    varlabel <- c("Q17r01_I_am_overwhelmed_by_the_number_of_apps_available_for_download", "Q22r03_I_feel_overwhelmed_by_the_number_of_digital_communications_I_receive",
                  "Q15r01_When_I_receive_a_message_online_I_tend_to_respond_right_away", "S03_Please_indicate_your_gender", "vAge_Age_breakdown")
    category <- c("a_Causes_of_Stress", "a_Causes_of_Stress", "a_Communication_Availability", "zz_Demo", "zz_Demo")
    vardata <- data.frame(profvars,varlabel,category,row.names=NULL)

    chartdatasplit <- split(chartdata, chartdata$variable)


    server <- function(input, output) {

    assigntables <- reactive({
      for (vars in profvars){
        local({
          var <- vars
          tablename <- paste0("table.",var)
          assign("tabledata",chartdatasplit[[var]],pos=1)  
          output[[tablename]] <- renderTable({tabledata}) ###appears this is only being done for last table
        })
      }
    })

      output$AllVars <- renderUI({
        ##for (i_var in 1:nrow(vardata)) {
        assigntables()
        return(apply(vardata,1,function(vars){
          fluidRow(column(12,offset=1,
            tableOutput(paste("table.",vars['profvars'],sep=''))),
            hr()
          )
        }))
      })
    }

    ui <- navbarPage("Seg Run",
                     tabPanel("Summary",
                              uiOutput("AllVars")
                     )
    )

    shinyApp(ui = ui, server = server)
LTR
  • 31
  • 4
  • There is a potential solution in [this question](http://stackoverflow.com/questions/22842354/outputing-n-tables-in-shiny-where-n-depends-on-the-data). Not sure why shiny is only taking the last table otherwise. May be a bug for the package, see [shiny issues](https://github.com/rstudio/shiny/issues) – cdeterman Mar 12 '15 at 13:50
  • I've been looking at that thread and will see if I can apply the same solution with xtable, thanks – LTR Mar 12 '15 at 16:52
  • please check this recent answer as well: https://stackoverflow.com/questions/31686773/shiny-dynamic-number-of-output-elements-plots – Beasterfield Jul 30 '15 at 13:55

1 Answers1

2

Here we go:

library(shiny)
library(xtable)

variable <- c("Q17r01", "Q17r01", "Q17r01", "Q22r03", "Q22r03", "Q22r03", "Q15r01", "Q15r01", "Q15r01", "S03", "S03", "vAge", "vAge", "vAge", "vAge", "vAge", "vAge")
responses <- c("A_T", "B_M", "C_B", "A_T", "B_M", "C_B", "A_T", "B_M", "C_B", "Female", "Male", "13 - 17", "18 - 24", "25 - 34", "35 - 44", "45 - 54", "55+")
grp1 <- c(33, 39, 28, 27, 20, 53, 88, 7, 5, 51, 49, 27, 8, 33, 14, 16, 2)
grp2 <- c(42, 46, 12,41, 45, 13, 64, 32, 4, 44, 56, 9, 22, 39, 13, 12, 4)
xAgg <- c(32, 49, 19, 26, 48, 26, 51, 38, 11, 45, 55, 12, 16, 30, 17, 14, 11)
chartdata <- data.frame(variable,responses,grp1,grp2,xAgg,row.names=NULL)

profvars <- unique(variable)
varlabel <- c("Q17r01_I_am_overwhelmed_by_the_number_of_apps_available_for_download", "Q22r03_I_feel_overwhelmed_by_the_number_of_digital_communications_I_receive",
              "Q15r01_When_I_receive_a_message_online_I_tend_to_respond_right_away", "S03_Please_indicate_your_gender", "vAge_Age_breakdown")
category <- c("a_Causes_of_Stress", "a_Causes_of_Stress", "a_Communication_Availability", "zz_Demo", "zz_Demo")
vardata <- data.frame(profvars,varlabel,category,row.names=NULL)

chartdatasplit <- split(chartdata, chartdata$variable)


server <- function(input, output) {

  tableize <- function(chartdatasplit){  ###can add additional arguments like dimension - add to where this is called also and how tabledata indexes
    tables <- list()
    for (x in names(chartdatasplit)){ ##go through all individually stored variable data frames in chartdatasplit list
      tabledata <- chartdatasplit[[x]]  ###function that returns a dataframe to use in table
      tables[[as.character(x)]] <- 
        print(xtable(tabledata, caption=paste("Variable:",x)),
           type="html", include.rownames = FALSE,
           html.table.attributes='class="data table table-bordered table-condensed"',
           caption.placement="top")
    }
    return(lapply(tables,paste))    
  }

  output$tables <- renderUI({
    out <- unlist(tableize(chartdatasplit))
      return(div(HTML(out),class="shiny-html-output"))
  })
} 

ui <- shinyUI(fluidPage(

  uiOutput("tables")
))


shinyApp(ui = ui, server = server)
discipulus
  • 2,665
  • 3
  • 34
  • 51
LTR
  • 31
  • 4
  • Hey, I've been using your solution but I'm feeding a df subset by reactive input but when it comes to displaying, it shows all the possible variables in the df instead of only those in the subset, any help would be greatly appreciated. – Rodrigo Cano Sep 28 '17 at 00:39