# catAndRun --------------------------------------------------------------------
#' Print Debug Messages Before and After Running Code
#'
#' @param messageText text to be printed before running the code
#' @param expr expressions to be run. Enclose more than one expression in
#' curly braces
#' @param newLine integer controlling new lines. 0: no extra new line, 1:
#' new line after \code{messageText}, 2: new line after "ok.", 3: new line
#' after both, \code{messageText} and "ok."
#' @param dbg logical. If \code{FALSE}, output is suppressed.
#' @param log_time logical. If \code{TRUE}, the time elapsed during the
#' evaluation of \code{expr} is printed.
#' @return This function returns the evaluation of \code{expr}. The result is
#' returned invisibly so that the result of an assignment as the last
#' expression in \code{exprt} does not show up on the console.
#' @export
#' @examples
#' for (newLine in 0:3) {
#'
#' catAndRun("work hard", newLine = newLine, {
#' cat("hard\nworking\n")
#' })
#'
#' cat("here.\n\n")
#' }
#'
catAndRun <- function(
messageText = "Running code", expr, newLine = 2L, dbg = TRUE, log_time = TRUE
)
{
catIf(dbg, messageText, "... ")
catNewLineIf(dbg && bitwAnd(newLine, 1))
start_time <- Sys.time()
result <- eval(expr, envir = -1)
catIf(dbg, "ok. ")
dt <- Sys.time() - start_time
catIf(dbg && log_time, sprintf("(%0.2f %s) ", dt, attr(dt, "units")))
catNewLineIf(dbg && bitwAnd(newLine, 2))
invisible(result)
}
# catIf ------------------------------------------------------------------------
#' Call cat If Condition Is Met
#'
#' @param condition if TRUE, cat is called, else not
#' @param \dots arguments passed to cat
#' @export
#'
catIf <- function(condition, ...)
{
if (condition) {
cat(...)
}
}
# catLines ---------------------------------------------------------------------
#' Print Character Vector to the Console
#'
#' Call cat on character vector, pasted with collapse = <new line>
#'
#' @param x vector of character representing text lines to be printed
#' @export
#'
catLines <- function(x)
{
cat(paste0(paste0(x, collapse = "\n"), "\n"))
}
# catNewLineIf -----------------------------------------------------------------
#' Print New Line Character to the Console if Condition is Met
#'
#' @param condition if \code{TRUE} the new line is printed else not
#' @return Returns the condition, invisibly so that it can be reused
#' @export
#'
catNewLineIf <- function(condition)
{
catIf(condition, "\n")
invisible(condition)
}
# clearConsole -----------------------------------------------------------------
#' Clear the R Console
#'
#' @export
#'
clearConsole <- function()
{
cat("\014\n")
}
# containsNulString ------------------------------------------------------------
#' Check for nul String in File
#'
#' @param filepath full path to file to be checked
#' @return \code{TRUE} if first two bytes of file are \code{<FF><FE>}, else
#' \code{FALSE}
#' @export
#'
containsNulString <- function(filepath)
{
x <- readBin(filepath, "raw", 2)
x[1] == as.raw(0xff) && x[2] == as.raw(0xfe)
}
# getNamesOfObjectsInRDataFiles ------------------------------------------------
#' Deprecated. Use \code{\link{listObjects}} instead.
#'
#' @param files.rdata vector of full paths to .RData files
#' @export
#'
getNamesOfObjectsInRDataFiles <- function(files.rdata)
{
warningDeprecated("getNamesOfObjectsInRDataFiles", "listObjects")
listObjects(files.rdata)
}
# getObjectFromRDataFile -------------------------------------------------------
#' Deprecated. Please use \code{\link{loadObject}} instead.
#'
#' @param file path to .RData file
#' @param objectname name of object to be loaded
#' @param dbg if \code{TRUE} a message about which object is loaded from which
#' file is shown
#' @return R object as specified in \emph{objectname}. If an object of that name does
#' not exist in the .RData file an error is thrown
#' @export
#'
getObjectFromRDataFile <- function(file, objectname = NULL, dbg = TRUE)
{
warningDeprecated("getObjectFromRDataFile", "loadObject")
loadObject(file, objectname, dbg)
}
# headtail ---------------------------------------------------------------------
#' Print First and Last Rows of a Data Frame
#'
#' Print the first and last rows of a data frame using head and tail,
#' respectively. Print the number of omitted rows
#'
#' @param x data frame
#' @param n total number of rows to be printed.
#' @param pattern pattern given to \code{sprintf} containing a \code{\%d}
#' placeholder to print the number of omitted rows
#' @return number of omitted rows, invisibly
#' @export
#' @examples
#' x <- data.frame(number = 1:26, letter = LETTERS)
#' headtail(x)
#' headtail(x, 10)
#' headtail(x, 16)
#' headtail(x[10:20, ], 10)
#'
headtail <- function(x, n = 6, pattern = "[%d rows omitted]")
{
if (! is.data.frame(x)) {
stop("headtail() is currently only defined for data frames")
}
if (nrow(x) <= n) {
print(x)
n_omitted <- 0
} else {
n2 <- n %/% 2
n_omitted <- nrow(x) - 2 * n2
print(utils::head(x, n2))
cat(sprintf(pattern, n_omitted), "\n")
print(utils::tail(x, n2))
}
invisible(n_omitted)
}
# listObjects ------------------------------------------------------------------
#' Get Names of Objects in .RData files
#'
#' @param files vector of full paths to .RData files
#' @export
#' @examples
#' ## Not run
#'
#' ## Search for available .RData files below "searchdir"
#' #searchdir <- "Y:/SUW_Department/Projects/SEMA/WP/20_Braunschweig"
#' #files <- dir(searchdir, pattern = "\\\\.RData$", recursive = TRUE, full.names = TRUE)
#'
#' ## Get the names of the objects in the .RData files
#' #objectsInFiles <- listObjects(files)
#'
#' ## Which file contains the object "DataQ"?
#' #dataQ.found <- sapply(objectsInFiles, function(x) {"DataQ" %in% x})
#'
#' #cat("DataQ was found in the following files:",
#' # paste(files[dataQ.found], collapse = "\n "))
#'
listObjects <- function(files)
{
# Create new environment into which the .RData files are to be loaded
# temporarily
testenvironment <- new.env(parent = .GlobalEnv)
# Prepare result list
objectsInFiles <- list()
# Loop through .RData files
for (i in seq_along(files)) {
cat(sprintf(
"Loading %d/%d: %s... ", i, length(files), basename(files[i])
))
load(file = files[i], envir = testenvironment)
cat("ok. ")
objectnames <- ls(envir = testenvironment)
objectsInFiles[[i]] <- objectnames
cat(length(objectnames), "objects found. ")
cat("Clearing workspace... ")
rm(list = ls(envir = testenvironment), envir = testenvironment)
cat("ok.\n")
}
# Delete the testenvironment
rm("testenvironment")
# Return the list of object names
structure(objectsInFiles, files = files)
}
# loadObject -------------------------------------------------------------------
#' Load R object from .RData file
#'
#' Load an R object of given name from a .RData file
#'
#' @param file path to .RData file
#' @param objectname name of object to be loaded
#' @param dbg if \code{TRUE} a message about which object is loaded from which
#' file is shown
#' @return R object as specified in \emph{objectname}. If an object of that name does
#' not exist in the .RData file an error is thrown
#' @export
#'
loadObject <- function(file, objectname = NULL, dbg = TRUE)
{
envir <- new.env()
catIf(dbg, sprintf("Loading '%s' from '%s'... ", objectname, file))
load(safePath(file), envir = envir)
# Get the names of the contained objects
objectnames <- ls(envir = envir)
if (is.null(objectname) || (! objectname %in% objectnames)) {
message_1 <- if (is.null(objectname)) {
"Please give an 'objectname'. "
} else {
sprintf("Object '%s' not found. ", objectname)
}
message_2 <- sprintf(
"Available objects in '%s':\n%s", file, stringList(objectnames)
)
stop(message_1, message_2, call. = FALSE)
}
catIf(dbg, "ok.\n")
# Return the object
get(objectname, envir = envir)
}
# printIf ----------------------------------------------------------------------
#' Call Print If Condition Is Met
#'
#' @param condition if TRUE, print is called, else not
#' @param x object to be printed
#' @param caption optional. Caption line to be printed with cat before printing
#' \emph{x}
#' @export
#'
printIf <- function(condition, x, caption = deparse(substitute(x)))
{
if (condition) {
catIf(caption != "", paste0(caption, ":\n"))
print(x)
}
}
# readPackageFile --------------------------------------------------------------
#' Read File from Package's extdata Folder
#'
#' @param file name of file (without path)
#' @param package name of the package from which to read the file
#' @param stringsAsFactors passed to \code{utils::read.csv} (default:
#' \code{FALSE})
#' @param \dots further arguments passed to \code{utils::read.csv}
#'
#' @return result of reading \code{file} with \code{utils::read.csv}
#' @export
#'
readPackageFile <- function(file, package, stringsAsFactors = FALSE, ...)
{
# If the package is not (yet) installed system.file() may not return the path
# to the installed package but the path to the where the package is developed!
path <- base::system.file("extdata", package = package)
if (path == "") {
path <- base::system.file("inst", "extdata", package = package)
}
file <- safePath(path, file)
utils::read.csv(file = file, stringsAsFactors = stringsAsFactors, ...)
}
# warningDeprecated ------------------------------------------------------------
#' Create Warning About a Deprecated Function
#'
#' @param old_name name of deprecated function
#' @param new_name name of new function to be used instead
#' @param parentheses logical. Should parentheses be printed after the names
#' in the output? Default: \code{TRUE}.
#' @export
#' @examples
#' \dontrun{
#' warningDeprecated("old_function()", "new_function()")
#' }
warningDeprecated <- function(old_name, new_name, parentheses = TRUE)
{
parens <- if (parentheses) "()" else ""
warning(call. = FALSE, sprintf(
"The function %s%s is deprecated.\nPlease use %s%s instead.",
old_name, parens, new_name, parens
))
}
# writeText --------------------------------------------------------------------
#' Write Text Lines to a File
#'
#' Write text to a file using \code{\link{writeLines}} and output a debug
#' message by default
#'
#' @param x vector of character representing the lines to be written to
#' \code{file}, passed to \code{\link{writeLines}}
#' @param file path to file to be written, passed to \code{\link{writeLines}}
#' @param type character string to be included in the debug message:
#' "Writing <type>'file-path' ..."
#' @param dbg if \code{TRUE}, debug messages are shown
#' @param \dots further arguments passed to \code{\link{writeLines}}
#' @return This function invisibly returns the path to the output \code{file}.
#' @export
#' @examples
#' # Define text to be written to file
#' x <- c("Hello", "world")
#'
#' # Write text to a temporary file and catch the file path
#' file <- writeText(x, tempfile(fileext = ".txt"))
#'
#' # Make the debug message more informative
#' writeText(x, file, type = "welcome file")
#'
#' # Read lines back and show on the console
#' catLines(readLines(file))
#'
writeText <- function(x, file, type = "", dbg = TRUE, ...)
{
catIf(dbg, sprintf(
"Writing %s%s'%s' ... ", type, ifelse(type == "", "", " "), file
))
writeLines(x, file, ...)
catIf(dbg, "ok.\n")
invisible(file)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.