R is a Lego Construction Set
Bioinformatics Core Facility CECAD
2026-09-11
git clone https://github.com/CECADBioinformaticsCoreFacility/Intermediate_R_Course_2026.git
https://cecadbioinformaticscorefacility.github.io/Intermediate_R_Course_2025/
Session 1 :: R is a Lego Construction Set
msg <- "This is a top-secret message!"
pool <- LETTERS
msg_chars <- strsplit(msg,"")[[1]]
u <- unique(msg_chars)
encrypt_chars <-
sample(pool,
size = length(u),
# no two message characters must map
# to the same encryption character
replace = FALSE
)
encrypt_chars <-
setNames(encrypt_chars, # vector to name
u # vector of names
)
This code contains fixed values:
What if we want to change them?
Copy and edit? Sounds messy …
encrypt <-
function(msg,
pool = LETTERS,
do_replace = FALSE,
cheat = FALSE
) {
msg_chars <- strsplit(msg,"")[[1]]
u <- unique(msg_chars)
encrypt_chars <-
sample(pool,
size = length(u),
replace = do_replace
)
encrypt_chars <-
setNames(encrypt_chars, # vector to name
u # vector of names
)
if (cheat)
# return the full map ..
result <- encrypt_chars[msg_chars]
else
# .. or just the encrypted message
result <- paste(encrypt_chars[msg_chars],
collapse="")
return(result)
}encrypt <-
function(msg,
pool = LETTERS,
do_replace = FALSE,
cheat = FALSE
) {
msg_chars <- strsplit(msg,"")[[1]]
u <- unique(msg_chars)
encrypt_chars <-
sample(pool,
size = length(u),
replace = do_replace
)
encrypt_chars <-
setNames(encrypt_chars, # vector to name
u # vector of names
)
if (cheat)
# return the full map ..
result <- encrypt_chars[msg_chars]
else
# .. or just the encrypted message
result <- paste(encrypt_chars[msg_chars],
collapse="")
return(result)
}function (msg, pool = LETTERS, do_replace = FALSE, cheat = FALSE)
{
msg_chars <- strsplit(msg, "")[[1]]
u <- unique(msg_chars)
encrypt_chars <- sample(pool, size = length(u), replace = do_replace)
encrypt_chars <- setNames(encrypt_chars, u)
if (cheat)
result <- encrypt_chars[msg_chars]
else result <- paste(encrypt_chars[msg_chars], collapse = "")
return(result)
}
encrypt <-
function(msg,
pool = LETTERS,
do_replace = FALSE,
cheat = FALSE
) {
msg_chars <- strsplit(msg,"")[[1]]
u <- unique(msg_chars)
encrypt_chars <-
sample(pool,
size = length(u),
replace = do_replace
)
encrypt_chars <-
setNames(encrypt_chars, # vector to name
u # vector of names
)
if (cheat)
# return the full map ..
result <- encrypt_chars[msg_chars]
else
# .. or just the encrypted message
result <- paste(encrypt_chars[msg_chars],
collapse="")
return(result)
}
[?introduce internal return(), and stop()?]
R/functions.R is a typical name for a file with small local functions:
More complex local functions should have their own source file:
Keep the encrypt() function in R/encrypt.R
source package: it is simply a folder with strictly defined content in plain textDESCRIPTION and NAMESPACE files, which describe how the package depends on other packages post-installation structure is operation system dependent and no longer plain textThe base R function package_dependencies queries information on the CRAN repository. Therefore we need to set a valid CRAN mirror, if we have not already done so:
List the strong dependencies of the plotting package ggplot2, i.e. those packages which need to be installed for ggplot2 to work:
While repositories are package sources, a destination folder for packages on our local system is called a library.
There may be more than a single library folder.
Function .libPaths() can be used to list them :
Bioi is a small and barebones package related to bioimaging . Let’s install it from CRAN:
Note that parameters "lib" and "repos" are superfluous in this case, because
.libPaths()[1] (the user library)
First remove it again …
Restart the R session for rstudio's Packages pane to realize the change!
Then do it rstudio-compliant:
Have an eye on what happens in the console:
It uses a different CRAN mirror from the one we had set above!
This happens because R had been restarted in between.
If you want a permanent value for an option,
set it in your .Rprofile file!
Checking an entry in the Packages list invokes the library() function:
library(PKG) without further arguments scans .libPath().
The first entry found with name “PKG”
attached to the search pathnamespace is loaded A shortcut to access one of PKG’s functions without library(PKG) is this:
PKG::function_I_want_to_run().
PKG would then be in the state loaded via namespace (and not attached).
Package A may “depend” on another package B because
"Imports:" B: A loads B’s functions via namespace"Depends:" on B: A attaches B to the search path"Suggests:" dependency allows A to be installed even if B cannot.Dependencies are declared in the DESCRIPTION and NAMESPACE files of a package.
(They should be readable in the package’s sub-folder of your library folder).
The risk of installation failure which comes with an Imports: or Depends: directive is not immediately obvious from the DESCRIPTION file!
Assume Package P depends on or imports four packages A, B, P1, and P2.
P's dependencies on A and B are much more risky
than those on P1 and P2:
https://www.sciencedirect.com/science/article/pii/S0164121223000055
The ballgown package provides tools for statistical analysis of assembled transcriptomes, including flexible differential expression analysis, visualization of transcript structures, and matching of assembled transcripts to annotation.
follow this link to create a dependency plot for a Bioconductor package
The easystats package orchestrates a small set of dependent packages,
with the mission
“to provide a unifying and consistent framework to tame, discipline, and harness the scary R statistics and their pesky model”
with a common GitHub page
An exemplary example of a package ecosystem in a nutshell!
Going Large: Bioconductor
Bioconductor has its own repository and installer,
The official Bioconductor website is very comprehensive, but can be overwhelming!
This site provides a more gentle, but still comprehensive walk-through.
Bioconductor also provides workflow packages, e.g. the rnaseqGene workflow.
Let’s look at its documentation.
And then there is the Tidyverse, a large and growing ecosystem of cross-compatible packages, with focus on workflows on 2D tables and graphical objects: