0

This has been bugging me for ages.

I have a function where the first argument either needs to be of the form function(data~ group_variable) OR of the form function(data, group = data$group_variable).

I have this function running smoothly in the console, but it is integral to my shiny app and it has been bugging me for ages, because both the data and the group are user-selected reactive objects, so it needs to take the form:

function(datasetInput() ~ !!input$group_variable) or some version thereof.

I haven't been able to find any combination of !!s, enquo(), substitute(), as.function(substitute()), etc that will make this work within the shiny app. as.Formula(substitute(data ~ group)) works in the console.

here is as minimal as I can make a reprex:

library(shiny)
library(shinyWidgets)
library(psych)
library(dplyr)
library(gt)
use <- function(name) {
  # consider future support for .json? 
  if (grepl(".csv", name)) {
    readr::read_csv(name)
  } else if (grepl(".xlsx", name)) {
    readxl::read_xlsx(name)
  } else if (grepl(".dta", name)) {
    haven::read_dta(name)
  } else if (grepl(".sav", name)) {
    haven::read_spss(name)
  } else if (grepl(".rda", name)) {
    load(name)
  } else {
    stop("unknown data type.")
  }
}

ui <- fluidPage(
  mainPanel(
    fileInput("FileInput", "Input Your Data Set"),
    helpText("Dataset must be one of: .csv, .sav, .dta, .xlsx, or .rda"), 
    materialSwitch(
      inputId = "ext_desc",
      label = "Extended Description", 
      value = FALSE,
      status = "primary"
    ),
    materialSwitch(
      inputId = "desc_by_group_bool",
      label = "Describe By A Group", 
      value = FALSE, 
      status = "primary"
    ),
    varSelectInput(
      inputId = "desc_group",
      label = "Select A Group",
      data = NULL, 
      width = "400px"
    ),
    gt::gt_output("description")
    
  )
)
server <- function(input,output, session){
  
  datasetInput <- reactive({
    infile <- input$FileInput
    if (is.null(infile))
      return(NULL)
    dat<-use(infile$datapath)
    names(dat) <-  gsub(" ", "_", names(dat), fixed = TRUE) 
    return(dat)
  })
  
  observeEvent(datasetInput(), {
    updateVarSelectInput(session, "desc_group", data = datasetInput())
  })
  
  desc <- reactive({
    req(datasetInput())
    if (input$desc_by_group_bool == FALSE) {
      datasetInput() %>%
        #select_if(is_numeric) %>%
        psych::describe(., fast = !(input$ext_desc),
                        omit = TRUE) %>%
        add_rownames(var = "Variable") %>%
        dplyr::select(-c(vars)) %>%
        dplyr::mutate(dplyr::across(is.numeric, round, 2)) %>%
        gt::gt() %>%
        gt::tab_options(
          column_labels.font.size = "small",
          table.font.size = "small",
          row_group.font.size = "small",
          data_row.padding = px(3)
        ) %>%
        gt::tab_header(title = paste0("Data Description"))
    } else {
      # datasetInput() %>%
      # select_if(is.numeric) %>%
      psych::describeBy( datasetInput() ~ !!input$desc_group,
                         # here we get "invalid argument type" error
                         fast = !(input$ext_desc),
                         mat = TRUE) %>%
        tibble::rownames_to_column() %>%
        select(-c(item, vars)) %>%
        dplyr::mutate(dplyr::across(is.numeric, round, 2)) %>%
        arrange(group1) %>%
        group_by(group1) %>%
        gt() %>%
        gt::tab_options(
          column_labels.font.size = "small",
          table.font.size = "small",
          row_group.font.size = "small",
          data_row.padding = px(3)
        ) %>%
        tab_header(title = paste0("Data Description") ,
                   subtitle = paste0("Grouped by: ",  input$desc_group)
        )
    }
    
    
  })
  
  output$description =  gt::render_gt(desc())
  
}
shinyApp(ui = ui, server = server)

The line causing the error--and the source of my question, is, forgive me, line 85 above.

Andrew McCartney
  • 191
  • 2
  • 10
  • 1
    Change that line to `psych::describeBy( datasetInput(), group = datasetInput()[[input$desc_group]]`. Also use `where` in `across` i.e `dplyr::mutate(dplyr::across(where(is.numeric), round, 2))` – Ronak Shah Oct 21 '20 at 00:51
  • 1
    looks like you updated/edited your code. the version using the `group = ` argument absolutely works. thank you so very much! where were you in March??? – Andrew McCartney Oct 21 '20 at 01:01

1 Answers1

1

There are various ways we can solve this. One way would be to use [[]] to subset the specific column. So change the describeBy line to :

psych::describeBy( datasetInput(), group = datasetInput()[[input$desc_group]]

Also add where in dplyr::across

dplyr::mutate(dplyr::across(where(is.numeric), round, 2))
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213