Introduction to jamsession

The jamsession package and functions are motived primarily to make your (my) analysis workflows as efficient as possible. They start with the simple idea of storing certain information in a central location, partly because it makes it easier to find months or years later. This workflow also works well if more often than not, you have multiple R sessions open and active, since these functions add the project name to the R prompt.

The R session and object files are versioned with the date, which has been an appropriate level of granularity, as well as being useful information when returning to work on past projects.

That said, this package mainly focuses on three aspects of R analysis work:

R sessions

This package stores and loads R sessions via .RData files from one stored location. These methods are useful are when analyzing data on different projects, where one may be asked to review data or results from projects years after the initial analysis. The methods here also store the R command history, which can be helpful when picking up where one left off.

Saving or loading an R session also sets the R prompt to the project name, which is particularly helpful when multiple R sessions are open an active at once.

R objects

This package also stored individual R objects in their own central location, in order to make it efficient to save and load objects in any R session, regardless the project or current working directory.

R functions

This package allows a clean mechanism of using a helper R script with functions to load and reload for active analysis use. Doing so minimizes copy-paste into active consoles, including via Rstudio, but also keeps function code in their own environment instead of the global environment. When stored in the global environment, the function code is saved along with the R session, which may not be desirable especially when using a large set of helper functions.

Motivations

Some motivations for this package:

  • make it efficient to find past R sessions and R objects by name, without the need to traverse down a nested file directory structure
  • make stored sessions and objects versioned by date, rather than using only the project or object name, and not needing to increment a version number every time a file is saved
  • provide a quick way to save and load R objects across different R sessions, to share useful objects in a structured, repeatable way
  • provide a clean method to load R functions from a separate file, to avoid having to copy-paste functions inside an R script, and to avoid R functions becoming part of the environment

Basic R session workflow

When starting a new project in a new R console, it is helpful to initiate the environment with the project name, by saving a new session. By default, session will be defined during this step, and the R prompt will change to display the session.

Note that we add the argument sessions_path=tempdir() only for this vignette, in typical use this argument is not used, because R sessions are stored in one location.

library(jamsession);
some_object <- data.frame(A=LETTERS[1:10]);
save_jamsession("jamsessionVignette",
   sessions_path=tempdir());
#> ##------ Fri Feb 26 11:51:47 2021 ------##
#> ##  (11:51:47) 26Feb2021:  save_jamsession(): Saved jamsession 'jamsessionVignette' to sessions_path '/var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg' 
#> ##  (11:51:48) 26Feb2021:  save_jamsession(): session_file:/var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg/inProgress_jamsessionVignette_26feb2021.RData
print(session);
#> [1] "jamsessionVignette"

You may then do some work and wish to save your session:

x <- rnorm(90);
y <- matrix(ncol=9, data=x);
## Usually only run like this:
# save_jamsession();

## For this vignette we add sessions_path
save_jamsession(sessions_path=tempdir());
#> ##------ Fri Feb 26 11:51:48 2021 ------##
#> ##  (11:51:48) 26Feb2021:  save_jamsession(): Saved jamsession 'jamsessionVignette' to sessions_path '/var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg' 
#> ##  (11:51:48) 26Feb2021:  save_jamsession(): session_file:/var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg/inProgress_jamsessionVignette_26feb2021.RData

You can later start R and pick up where you left off, which is simulated here by removing these objects, then loading the session:

rm(y);
load_jamsession("jamsessionVignette",
   sessions_path=tempdir());
#> ##  (11:51:48) 26Feb2021:  load_jamsession(): Loading session: /var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg/inProgress_jamsessionVignette_26feb2021.RData 
#> ##  (11:51:48) 26Feb2021:  load_jamsession(): Loaded session:jamsessionVignette into environment 'R_GlobalEnv' 
#> ##  (11:51:48) 26Feb2021:  load_jamsession(): jamba::setPrompt()
print(head(y));
#>            [,1]       [,2]       [,3]       [,4]       [,5]       [,6]
#> [1,] -0.1746496  1.2632106  0.1421545 -2.0290540  1.1963749 -0.3291158
#> [2,]  0.6678865 -0.6171401  2.0941790  0.7411257 -0.9824536  1.0532583
#> [3,] -0.5410615  0.2788621  0.6639901 -0.3473734 -1.1362320  0.2973083
#> [4,] -0.1960676  0.1699450  0.4345637 -0.6412012  0.8496156 -0.5059457
#> [5,]  0.8404091 -0.8303865 -0.1707804  0.5531530 -0.2820454  0.1809520
#> [6,] -1.1545893  0.4513572  0.2015576  0.1701800 -1.1425453  0.3062582
#>             [,7]      [,8]         [,9]
#> [1,] -1.14345053 0.8983498 -0.231920320
#> [2,]  0.59193888 0.1874275 -1.875015455
#> [3,] -1.12590604 0.3010680 -0.005386849
#> [4,] -1.68921139 0.9326318 -0.475984069
#> [5,]  0.99822743 0.3392999  0.151604623
#> [6,] -0.09326957 0.8738715  1.239727053

Saving R objects

If you want to save an object, it is best to name it something specific before saving it. The call the saveObject() function with the name of the object:

Note that we add the argument objects_path=tempdir() only for this vignette, in typical use this argument is not used, because R objects are stored in one location.

jamsessionVignetteY <- t;
save_object("jamsessionVignetteY",
   objects_path=tempdir());
#> ##  (11:51:49) 26Feb2021:  save_objects(): Object saved:/var/folders/9z/y1_0kf711fx3lgc68w1k27xr0000gs/T//Rtmp8knAHg/jamsessionVignetteY_26feb2021.RData

You can then load this object from any R console using load_object(), simulated here by removing the object, then loading it from the saved object file:

rm(jamsessionVignetteY);
load_object("jamsessionVignetteY",
   objects_path=tempdir());
#> ##  (11:51:49) 26Feb2021:  load_object(): Loaded object: 'jamsessionVignetteY'
print(head(jamsessionVignetteY));
#>                 
#> 1 function (x)  
#> 2 UseMethod("t")

Loading R functions

R is a functional programming language, which makes it especially useful and powerful to write and re-use custom functions. Most R analysts have built up a long list of useful helper functions, either for re-use across all their projects, or written specifically per project. Either way, these functions need to be loaded into the R workspace, and very likely will need to be refreshed as the functions are updated over time.

We demonstrate having a utility script by creating a temporary script, then using refresh_functions().

## Create a simple R script function fun()
r_script <- "
#' Simple print function
#' 
#' This function simply runs print()
#'
#' @param x any R object that can be printed.
#' @param ... additional arguments are passed to print().
#'
#' @export
printfun <- function(x, ...) {print(x, ...)};
";

## Save to a file in tempdir
fn_file <- file.path(tempdir(),
   "jamvignette_functions.R");
## Save the R script to a file
cat(r_script, file=fn_file);

Now the file has been saved under the name “jamsession”. We can load this file with refresh_functions().

For this vignette, we include argument functions_path=tempdir(), but this argument is usually not necessary, when functions are saved to a common path. Run jamvignette_paths() to see or set the expected paths.

## Load the R script
refresh_functions("jamvignette",
   functions_path=tempdir());
#> ##  (11:51:50) 26Feb2021:  refresh_functions(): Loaded temporary package as 'jamvignette'

## search() shows the environments including jamvignette
print(search());
#>  [1] ".GlobalEnv"           "devtools_shims"       "package:jamvignette" 
#>  [4] "package:S4Vectors"    "package:BiocGenerics" "package:parallel"    
#>  [7] "package:stats4"       "package:matrixStats"  "package:colorspace"  
#> [10] "package:farver"       "package:crayon"       "package:jamsession"  
#> [13] "package:stats"        "package:graphics"     "package:grDevices"   
#> [16] "package:utils"        "package:datasets"     "package:methods"     
#> [19] "Autoloads"            "tools:callr"          "package:base"

## find() to show where printfun is located
find("printfun")
#> [1] "package:jamvignette"

Lastly, we can run the printfun() function to show it works.

printfun(LETTERS[1:10]);
#>  [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J"