Last active
October 5, 2023 05:14
-
-
Save scarnecchia/be1aa85f576cc82ffd7461a5b37fcea9 to your computer and use it in GitHub Desktop.
This script uses an input file `tabvars` to write a SAS program which then reads in CSV files, formats them, and outputs them as sas7bdat datasets
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#' Runs a SAS program using the specified SAS executable and program file. | |
#' | |
#' @param executable The path to the SAS executable. | |
#' @param saspath The path to the SAS program file. | |
#' | |
#' @return Returns nothing, but prints a message to the console indicating whether the execution was successful or not. | |
#' | |
#' @examples | |
#' run_sas("C:/Program Files/SASHome/SASFoundation/9.4/sas.exe", "C:/my_sas_program.sas") | |
#' | |
#' @importFrom xfun normalize_path in_dir msg_cat | |
#' @importFrom fs path_dir | |
run_sas <- function(executable, saspath) { | |
saspath <- xfun::normalize_path(saspath) | |
executable <- xfun::normalize_path(executable) | |
log <- fs::path_dir(executable) | |
xfun::in_dir(saspath, { | |
return.code <- | |
shell(paste("sas.exe -SYSIN", executable, "-log", log, "-print", log)) | |
}) | |
if (return.code == 0) { | |
xfun::msg_cat(paste("Execution of", executable, "successful!")) | |
} else { | |
message(paste("SAS Process returned nonzero return code:", return.code)) | |
} | |
} | |
#' Extracts SAS errors from a log file and checks for empty output files | |
#' | |
#' This function takes in a path to a SAS log file and a path to a directory containing | |
#' output files generated by the SAS process. It reads the log file, extracts any lines | |
#' that start with "ERROR", and returns them as a character vector. It also checks each | |
#' output file in the directory to see if it is empty, and prints a message if it is. | |
#' | |
#' @param log A character string specifying the path to the SAS log file | |
#' @param msoc A character string specifying the path to the directory containing output files | |
#' @return A character vector containing any lines from the log file that start with "ERROR" | |
#' @export | |
sas_errors <- function(log, msoc) { | |
log <- xfun::normalize_path(log) | |
msoc <- xfun::normalize_path(msoc) | |
log <- suppressWarnings(try(readLines(log), silent = TRUE)) | |
errors <- log %>% | |
stringi::stri_subset_regex('^ERROR.*:') | |
msoc <- fs::dir_ls(msoc) | |
for (i in msoc){ | |
print(i) | |
if(isTRUE(file.size(i) == 0L)){ | |
message('SAS process returned empty file:', i) | |
} | |
} | |
return(errors) | |
} | |
# Initialize a vector containing table identifiers ("enr", "dem", "dth") | |
tablist <- c("enr", "dem", "dth") | |
# Write the SAS 'libname' statement to the 'create_tables.sas' file | |
# The path for the 'libname' is obtained using `fs::path_wd()` | |
readr::write_file(glue::glue('libname msoc "{fs::path_wd("output")}/";\n\n'), | |
file=fs::path_wd("SAS", "create_tables.sas"), append=FALSE) | |
# Loop over each table identifier in 'tablist' using purrr::map | |
purrr::map(tablist, function(tabid) { | |
# Get the current working directory | |
path <- fs::path_wd() | |
# Filter 'tabvars' data frame to keep only rows where 'TabCD' matches the current 'tabid' | |
.tmp <- dplyr::filter(tabvars, TabCD == toupper({{tabid}})) | |
# Open a sink to append the SAS code to 'create_tables.sas' | |
sink(file="SAS/create_tables.sas", append=TRUE) | |
# Generate and write SAS code for creating a table | |
cat(paste0("\n", "data msoc.", tabid, ";", "\n"), | |
paste('infile', paste0('"', xfun::normalize_path(fs::path(path, "output", tabid, ext = "csv")),'"'), 'dlm="," dsd truncover firstobs=2;', "\n"), | |
paste0("length ", paste0(.tmp$Variable, " ", .tmp$length, collapse = " "), ";\n"), | |
paste0("informat ", paste0(.tmp$Variable, " ", .tmp$informat, collapse = " "), ";\n"), | |
paste0("format ", paste0(.tmp$Variable, " ", .tmp$format, collapse = " "), ";\n"), | |
paste0("input ", paste0(.tmp$Variable, " ", .tmp$input, collapse = " "), ";\n"), | |
"run;\n\n" | |
) | |
# Close the sink | |
sink() | |
}) | |
# Run the generated SAS program | |
# This assumes a specific path for the SAS executable | |
run_sas(fs::path_wd("SAS", "create_tables.sas"), saspath = "C:/Program Files/SASHome/SASFoundation/9.4") | |
# Check the SAS log for errors | |
# This assumes a specific log path and output directory | |
sas_errors(log="SAS/create_tables.log", msoc = "output") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment