Search code examples
ruser-inputinteractivecensus

How to supply user input programmatically to an interactive function in R (specifically in the totalcensus package)


I'm writing an R script that has some interactive functions that stop the code to wait for user input. I need the script to run fully automated so that Travis-CI can build it independently. How do I supply the user input programmatically so that the code runs continuously instead of stopping for interactive input?

Specifically, I'm using the read_acs5year function from the totalcensus package in R, and when I run this code:

acs_data_2008_2012_via_totalcensus <-
  read_acs5year(
    year = 2012,
    states = "AL",
    table_contents =
      "B01003",
    summary_level = "tract",
    with_margin = TRUE
)

it outputs this to the console:

Do you want to download data generated from decennial census 2010? This dataset is necessary for processing all summary files.
1: yes
2: no

Selection:

and then waits for user input. I want to give the function the input of 1 automatically.


Solution

  • As suggested by @NelsonGon you could create your own version of the function by changing the menu option

    get_data <- function(year,
                          states,
                          table_contents = NULL,
                          areas = NULL,
                          geo_headers = NULL,
                          summary_level = NULL,
                          geo_comp = "total",
                          with_margin = FALSE,
                          dec_fill = NULL,
                          show_progress = TRUE){
    
      ### check if the path to census is set ###
    
      if (Sys.getenv("PATH_TO_CENSUS") == ""){
        message(paste(
         "Please set up the path to downloaded census data",
         "following the instruction at",
         "https://github.com/GL-Li/totalcensus."
       ))
        return(NULL)
      }
    
    
      ### check whether to download data ###
    
      path_to_census <- Sys.getenv("PATH_TO_CENSUS")
    
      # check if need to download generated data from census2010
      generated_data <- paste0(path_to_census, "/generated_data")
      if (!file.exists(generated_data)){
        download_generated_data()
      } else {
        version_file <- paste0(generated_data, "/version.txt")
        if (!file.exists(version_file)){
          download_generated_data()
        } else {
          version = readChar(version_file, 5)
          if (version != "0.6.0"){
             download_generated_data()
          }
         }
       }
    
      # check whether to download acs5year data
      not_downloaded <- c()
      for (st in states){
         # only check for geoheader file
         if (!file.exists(paste0(
           path_to_census, "/acs5year/", year, "/g", year, "5",
           tolower(st), ".csv"
        ))){
           not_downloaded <- c(not_downloaded, st)
         }
       }
      if (length(not_downloaded) > 0){
          cat(paste0(
           "Do you want to download ",
           year,
           " ACS 5-year survey summary files of states ",
            paste0(not_downloaded, collapse = ", "),
           " and save it to your computer? ",
           "It is necessary for extracting the data."
         ))
    
         if (TRUE){
           download_census("acs5", year, not_downloaded)
         } else {
           stop("You choose not to download data.")
         }
        }
    
    
      ### read data ###
    
      if (is.null(summary_level)) summary_level <- "*"
         states <- toupper(states)    # allow lowcase input
      if (is.null(areas) + is.null(geo_headers) == 0){
         stop("Must keep at least one of arguments areas and geo_headers NULL")
       }
    
      # add population to table contents so that it will never empty, remove it
      # from table_contents if "B01003_001" is included.
       if (any(grepl("B01003_001", table_contents))){
           message("B01003_001 is the population column.")
       }
    
       table_contents <- table_contents[!grepl("B01003_001", table_contents)]
       table_contents <- c("population = B01003_001", table_contents) %>% unique()
    
       content_names <- organize_tablecontents(table_contents) %>% .[, name]
       table_contents <- organize_tablecontents(table_contents) %>%  .[, reference] %>%
         toupper()    # allow lowcase in reference input
    
       # turn off warning, fread() gives warnings when read non-scii characters.
       options(warn = -1)
    
        if (!is.null(areas)){
          dt <- read_acs5year_areas_(
                year, states, table_contents, areas, summary_level, geo_comp,
               with_margin, dec_fill, show_progress
          )
        } else {
           geo_headers <- unique(geo_headers)
           dt <- read_acs5year_geoheaders_(
             year, states, table_contents, geo_headers, summary_level, geo_comp,
             with_margin, dec_fill, show_progress
         )
        }
    
        setnames(dt, table_contents, content_names)
    
        if (with_margin){
            setnames(dt, paste0(table_contents, "_m"),
                    paste0(content_names, "_margin"))
        }
    
        options(warn = 0)
        return(dt)
      }
    

    and then use this nee function instead of read_acs5year. It would automatically be downloaded now without waiting for any user input.

     get_data(
         year = 2012,
         states = "AL",
         table_contents = "B01003",
         summary_level = "tract",
         with_margin = TRUE
     )