---
title: "sassy"
output: rmarkdown::html_vignette
vignette: >
%\VignetteIndexEntry{sassy}
%\VignetteEngine{knitr::rmarkdown}
%\VignetteEncoding{UTF-8}
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>"
)
```
The **sassy** system is a coherent and well-designed
ecosystem for managing and reporting on data in R. The goal of the system
is to make R capable of producing any kind of output that can be
produced in SAS®. The system includes eight R packages.
## Included Packages
The **sassy** package itself is a meta-package that contains the following packages.
Each of these packages contribute a needed area of functionality missing
from R:
* **[logr](https://logr.r-sassy.org)**: Produces a traceable log
* **[fmtr](https://fmtr.r-sassy.org)**: Provides functions for formatting
data and a creating a format catalog
* **[libr](https://libr.r-sassy.org)**: Gives you the ability to define a
libname, generate a data dictionary, and simulate a data step
* **[procs](https://procs.r-sassy.org)**: A set of functions that simulate
SAS® procedures. Package includes simulations of PROC FREQ, PROC MEANS,
PROC TTEST, PROC TRANSPOSE, PROC SORT, and more.
* **[reporter](https://reporter.r-sassy.org)**: A reporting package with easy
layout capabilities and the
ability to write reports in TXT, RTF, PDF, HTML, and DOCX file formats
* **[common](https://common.r-sassy.org)**: A set of utility functions
shared across the **sassy** family of packages, and often
useful in their own right.
* **[macro](https://macro.r-sassy.org)**: A macro language for R that allows
easy, text-based meta-programming.
Each of the packages is self-contained, and can be used in isolation.
However, when used collectively, the packages work
together to create an integrated and productive user experience.
## How to Use
Let's first get a basic
understanding of how to use each package individually.
### Create a Log
Programmers coming from SAS are usually surprised to find there is no
automatic logging in R. The **logr** package was written to provide a simple
logging system that anyone can use.
There are three steps to creating a log:
1) Open the log
2) Write to the log
3) Close the log
Below is a minimal example that illustrates how to create a log with the
**logr** package. The `put()` function writes any R object to the log, similar
to a SAS %put statement:
```{r eval=FALSE, echo=TRUE}
library(sassy)
# Open the log
log_open("Example1.log")
# Write to the log
put("Here is something to send to the log.")
# Close the log
log_close()
```
The generated log looks like this:
```
=========================================================================
Log Path: ./log/Example1.log
Working Directory: C:/Projects/Archytas/WUSS/Code
User Name: dbosa
R Version: 4.3.1 (2023-06-16 ucrt)
Machine: SOCRATES x86-64
Operating System: Windows 10 x64 build 22621
Base Packages: stats graphics grDevices utils datasets methods base Other
Packages: procs_1.0.3 reporter_1.4.2 libr_1.2.8 logr_1.3.4 fmtr_1.6.0
common_1.0.9 sassy_1.2.1
Log Start Time: 2023-10-01 00:20:10.31621
=========================================================================
Here is something to send to the log.
NOTE: Log Print Time: 2023-10-01 00:20:10.491874
NOTE: Elapsed Time: 0.174062013626099 secs
=========================================================================
Log End Time: 2023-10-01 00:20:11.291764
Log Elapsed Time: 0 00:00:00
=========================================================================
```
For a complete explanation of the capabilities of the **logr**
package, see the [logr](https://logr.r-sassy.org) documentation site.
### Create a Libname
The **sassy** system provides a `libname()` function that is quite similar to a
SAS® libname statement. The function will import a set of related datasets
from a specified directory, and assign a name to the entire set. The following
code imports a set of related csv files and assigns them to the name “sdtm”:
```{r eval=FALSE, echo=TRUE}
library(sassy)
# Define library
libname(sdtm, "./data", "csv")
```
Once the datasets have been imported, the libname can be accessed
using R list syntax. That means the datasets are now available from the
libname using the dollar sign ($). In **RStudio®**, it looks like this:
The **libr** package not only allows you to easily access a directory of
datasets. It also allows you to add, remove, and edit datasets in the
library. The `libname()` function can import SAS datasets, CSV files, R
data files, Excel files, and more. See the [libr](https://libr.r-sassy.org)
documentation for additional information.
### Data Formatting
The idea of a *format* is another foundational concept in SAS software.
In R, formatting is spread over many functions. The **fmtr** package aims to
consolidate and simplify formatting in R, and make it more similar to the
way you work with formats in SAS. The package contains functions to
create a user-defined format, apply formats to vectors and data frames,
and create format catalogs.
The following example shows you how to create a user-defined format,
and apply it to a column of data. Notice that the `value()` function is
similar to the statements inside a SAS PROC FORMAT procedure, and that
the `fapply()` function is defined in a way that is reminiscent of a SAS
data step `put()` function:
```{r eval=FALSE, echo=TRUE}
library(sassy)
#Create libname
libname(sdtm, "./data", "csv")
# Copy DM dataset
dat <- sdtm$DM
# Create user-defined format
fmt_sex <- value(condition(is.na(x), "Missing"),
condition(x == "M", "Male"),
condition(x == "F", "Female"),
condition(TRUE, "Other"))
# Create a new column of formatted values
dat$SEXF <- fapply(dat$SEX, fmt_sex)
# View a few rows of data
print(dat[1:5, c("USUBJID", "SEX", "SEXF")])
# # A tibble: 5 x 3
# USUBJID SEX SEXF
#
# 1 ABC-01-049 M Male
# 2 ABC-01-050 M Male
# 3 ABC-01-051 M Male
# 4 ABC-01-052 F Female
# 5 ABC-01-053 F Female
```
The `value()` and `fapply()` functions are a small part of the very capable
**fmtr** package. See the [fmtr](https://fmtr.r-sassy.org) documentation
for a complete list of functions.
### Perform a Datastep
In SAS, the data step is the go-to procedure for manipulating data.
The data step provides row-by-row processing of a dataset. In R, however,
data processing is typically done column-by-column. This change in
orientation is difficult for SAS programmers to adjust to. Also, there
are some types of processing that are easy to do in a data step, but are
quite difficult to do with column-wise processing.
For these reasons, the **sassy** system offers a `datastep()` function.
It is part of the **libr** package. The `datastep()` function simulates the
most basic functionality of a SAS data step. Like a SAS data step, it
allows you to reference data.frame variables unquoted, and to make up
variables on the fly. It also provides basic data shaping parameters
like keep, drop, rename, and retain. The example below demonstrates a
simple data step that performs age categorization on the sdtm.DM dataset.
```{r eval=FALSE, echo=TRUE}
library(sassy)
#Create libname
libname(sdtm, "./data", "csv")
# Perform data step
dm_mod <- datastep(sdtm$DM, keep = c("USUBJID", "AGE", "AGECAT"), {
if (AGE >= 18 & AGE <= 24)
AGECAT <- "18 to 24"
else if (AGE >= 25 & AGE <= 44)
AGECAT <- "25 to 44"
else if (AGE >= 45 & AGE <= 64)
AGECAT <- "45 to 64"
else if (AGE >= 65)
AGECAT <- ">= 65"
})
# Print dm_mod to console
print(dm_mod)
# # A tibble: 87 x 3
# USUBJID AGE AGECAT
#
# 1 ABC-01-049 39 25 to 44
# 2 ABC-01-050 47 45 to 64
# 3 ABC-01-051 34 25 to 44
# 4 ABC-01-052 45 45 to 64
# 5 ABC-01-053 26 25 to 44
# 6 ABC-01-054 44 25 to 44
# 7 ABC-01-055 47 45 to 64
# 8 ABC-01-056 31 25 to 44
# 9 ABC-01-113 74 >= 65
# 10 ABC-01-114 72 >= 65
# # ... with 77 more rows
```
The `datastep()` function, like the `libname()` function, is one of
several powerful functions in the **libr** package. See the
[libr](https://libr.r-sassy.org) documentation for additional examples
and extended discussion.
### Generate Statistics
One of the most frustrating things about working with R is that
the statistics don’t always match SAS. It is not that the R statistics
are wrong. It is that R functions often have different default settings
or different algorithms, which lead to different results. Both tools
are correct. But they are correct in different ways.
The **procs** package was developed to give you an easy way to produce
statistics in R that match SAS. The statistical functions in the package
include `proc_freq()`, `proc_means()`, `proc_ttest()`, and `proc_reg()`.
For convenience, the package also includes `proc_sort()`,
`proc_transpose()`, and `proc_print()`. Collectively,
these functions represent the core of the **sassy** system.
Let us look at an example. In this example, we will generate
frequencies and means on some variables in the DM dataset, combine
them into a single list, and print everything to the viewer:
```{r eval=FALSE, echo=TRUE}
library(sassy)
# Define data library
libname(sdtm, "./data", "csv")
# Generate Frequencies
res <- proc_freq(sdtm$DM,
tables = c("ARM", "SEX", "SEX * ARM"),
output = "report")
# Generate Means and append to Frequencies
res[["AGE"]] <- proc_means(dat, var = "AGE",
class = "ARM",
output = "report")
# Print everything to viewer
proc_print(res, titles = "Analysis of Demographics Dataset")
```
When working in RStudio, the above code will send the following to the viewer:
Note that you may also print the report to a file. Use the "file_path"
and "output_type" parameters to specify where to print the report and what
type of report to create.
See the [procs](https://procs.r-sassy.org) package documentation for
additional information.
### Write a Report
If you want to create an HTML report in R, there are many packages
to choose from. For paged file formats such as text, RTF, DOCX, and PDF,
however, options are much more limited. The **reporter** package provides
easy page-based reporting with a choice of output types. It is currently
the closest R package to matching the capabilities of SAS PROC REPORT and ODS.
There are four steps to creating a **reporter** report:
1) Create report content
2) Create report
3) Add content to report
4) Write the report
Below is an example of a simple data listing using the **libr** and **reporter**
packages. Observe that the **reporter** package will automatically set
column widths, wrap pages, and put page breaks at the appropriate locations.
If you want to override the automatic settings, you can use the `define()`
function. Also note the ability to set an ID variable that is
repeated on every page:
```{r eval=FALSE, echo=TRUE}
library(sassy)
# Define data library
libname(sdtm, "./data", "csv")
# Create report content
tbl <- create_table(sdtm$DM) |>
define(RACE, width = 2.5) |>
define(ETHNIC, width = 2.5) |>
define(USUBJID, id_var = TRUE)
# Create report and add content
rpt <- create_report("./output/example.pdf", font = "Courier",
output_type = "PDF") |>
page_header("Sponsor: Company", "Study: ABC") |>
titles("Listing 1.0", "Sample Demographics Data") |>
add_content(tbl) |>
page_footer(Sys.time(), "CONFIDENTIAL", "Page [pg] of [tpg]")
# Write out the report
write_report(rpt)
```
Here is the first page of the report created by the above example code:
See the [reporter](https://reporter.r-sassy.org) documentation site for
more examples and complete function documentation.
### Useful Utilities
The above packages comprise the main body of the sassy system.
In addition, there is a package of utility functions called **common**.
The functions in this package perform useful tasks that are not
easily done using Base R. Here is a list of functions in the package
and a short explanation of each:
* `v()`: A generalized NSE quoting function.
* `sort.data.frame()`: An overload to the sort function for data frames.
* `labels.data.frame()`: An overload to the labels function for data frames.
* `%p%`: An infix operator for the paste0() function.
* `%eq%`: An enhanced equality operator.
* `Sys.path()`: A function to return the path of the currently running program.
* `roundup()`: A rounding function that matches SAS® rounding.
* `file.find()`: A function to search for a file on the file system.
* `dir.find()`: A function to search for a directory on the file system.
* `find.names()`: A function to search for variable names on a data.frame.
* `copy.attributes()`: A function to copy column attributes from one data frame to another.
* `supsc()`: A function to get UTF-8 superscript characters.
* `subsc()`: A function to get UTF-8 subscript characters.
* `symbol()`: A function to lookup UTF-8 symbols.
* `spaces()`: A function to create a string of blank spaces.
* `changed()`: A function to identify changed values in a vector or data frame.
For more information, see the [common](https://common.r-sassy.org) package
documentation.
### Write a Macro
The **sassy** system also contains a macro language. It is contained in a package
called **macro**, and mimics the basic functionality of the SAS macro language.
The macro commands are contained inside R code comments, but otherwise
resemble SAS macro functions. Here is a simple example:
```
library(sassy)
#%let x <- 1
#%if (&x == 1)
print("x is one!")
#%else
print("x is something else!")
#%end
```
As shown above, the R macro language supports macro variable assignments
and macro conditions. It also supports do loops, include, user-defined
macro functions, and several built-in macro functions. See the
[macro](https://macro.r-sassy.org) documentation for a complete
explanation of this interesting package.
## Validation
The **sassy** system is validated. For the **procs** package, all functions
have been compared to SAS. The validation documentation is
[here](https://r-sassy.org/validation/Procs_Validation.pdf)
In addition, there are IQ and OQ validation routines built into
the **sassy** package itself. These routines can be used for on-site
qualification of the packages in your local environment. See the
`run_iq()` and `run_oq()` documentation in the **sassy** package.
## Next Steps
To explore the **sassy** system further, please see the following vignettes:
* [Program Gallery](sassy-gallery.html): A collection of sample programs written
using the **sassy** system.
* [Papers and Training](sassy-training.html): Papers and training videos
on different aspects of the ecosystem.