The {svMisc} package contains a large collection of functions that are useful in the context of (G)UI (Graphical) User Interface development, and also, of more general usage. Here is a series of functions you should look at.
In R, you access man pages for the various R objects with
help(topic)
, or ?topic
. But, if
topic
is not found, these function do not return a very
useful information. For instance, if you want to make a Kalman filtering in R,
you may be inclined to search for the topic kalman
?kalman
#> No documentation for 'kalman' in specified packages and libraries:
#> you could try '??kalman'
OK, it is suggested to use ??
to search the
documentation for kalman
. However, using
about()
instead immediately produces a more useful
result:
library(svMisc)
about("kalman")
#> 'kalman' not found, do you mean?
#> stats::KalmanForecast, stats::KalmanLike, stats::KalmanRun, stats::KalmanSmooth
#> Searching keyword in all R help pages for ''...
… and it also provides a list of potential man pages that could
interest you. In case the topic is found, about()
does the
same as help()
and shows the page (try with
about("log")
, for instance). If you still have not found
what you are looking for, you could try to search on the Web by using
search_web()
.
You may also be interested by is_help()
that indicates
if an object is associated with a man page, and if it has a running
example.
In R, the use of library()
to load a
package is very confusing. Given the number of
questions raised about it, one could consider another function to load R
packages in memory. svMisc
proposes package()
.
That function loads one or several R packages as silently as possible
and it returns TRUE
only if all the
packages are loaded. Otherwise, the list of missing packages is
recorded1, and one could simply issue
Install()
to install them. This is indeed a semi-automatic
installation mechanisms for R packages. The UseR still masters the
process, but it is more straightforward.
If you need to perform an analysis in batch mode, you may be happy
with batch()
and progress()
. The first
function runs a function sequentially on all items allowing for
an informative message in case of failure. Also,
batch()
provides a mechanism to recover from the error, so
that following items in the list are also analyzed. Indeed, if you use a
simple for()
loop or applyXXX()
functions, the
execution is stopped at the first error encountered. Imagine 500 items
to process, and an error that appears at the second one… it leaves you
498 items unanalyzed! allows to continue to the next item.
The example shows a fake batch process of files, which fails randomly. Here is the function to run sequentially:
fake_process <- function(file) {
message("Processing ", file, "...")
flush.console()
Sys.sleep(0.5)
if (runif(1) > 0.7) {# Fail
warning("fake_process was unable to process ", file)
invisible(FALSE)
} else invisible(TRUE)
}
The key aspect here is that you function, instead of using
stop()
must use warning()
and return
FALSE
. Otherwise, in case of success, it should return
TRUE
. Then, calling your function on a series of objects is
straightforward:
# Run it in batch mode on ten items
batch(paste0("file", 1:10), fake_process)
#> Running the batch process with fake_process...
#>
#> Progress: 1 on 10 Progress: 2 on 10 Progress: 3 on 10 Progress: 4 on 10 Progress: 5 on 10 Progress: 6 on 10 Progress: 7 on 10
#> Warning in fun(item, ...): fake_process was unable to process file7
#>
#> Progress: 8 on 10
#> Warning in fun(item, ...): fake_process was unable to process file8
#>
#> Progress: 9 on 10 Progress: 10 on 10
#> Warning in fun(item, ...): fake_process was unable to process file10
#> Processed successfully 7 items on 10 (see .last.batch)
In case an error occurred, the information is recorded i,
.last.batch
:
.last.batch
#> [1] FALSE
#> attr(,"items")
#> [1] "file1" "file2" "file3" "file4" "file5" "file6" "file7" "file8"
#> [9] "file9" "file10"
#> attr(,"ok")
#> [1] TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE TRUE FALSE
The items
and ok
attributes are also
available from that object for further inspection and action.
If you run batch()
in R, you noted also the
progress()
ion message that appeared. Indeed the
progress()
function allows to display such a message,
either as a text at the R console, or in a dialog box. There are many
different forms, see the man page ?progress
. for instance,
here is a progress bar in percent, stopped at 75% () you need to call
progress()
with a value higher than
max.value =
to dismiss it):
The $
operator is not applicable on functions. It is not
meaningful in that context. Yet, it may be convenient to use it in
certain conditions. From the example of ?subsettable
:
foo <- structure(function(x, type = c("histogram", "boxplot"), ...) {
type <- match.arg(type, c("histogram", "boxplot"))
switch(type,
histogram = hist(x, ...),
boxplot = boxplot(x, ...),
stop("unknow type")
)
}, class = c("function", "subsettable_type"))
foo
#> function (x, type = c("histogram", "boxplot"), ...)
#> {
#> type <- match.arg(type, c("histogram", "boxplot"))
#> switch(type, histogram = hist(x, ...), boxplot = boxplot(x,
#> ...), stop("unknow type"))
#> }
#> attr(,"class")
#> [1] "function" "subsettable_type"
# This function can be used as usual:
foo(rnorm(50), type = "histogram")
The capture.output()
function from the ‘utils’ package
can capture output usually send to the R console, but it does so in an
imperfect way. If you want to capture output exactly as it
would appear at the R console, you could use
capture_all()
:
captured <- capture_all(parse_text('1:2 + 1:3'), split = FALSE)
#> Warning in 1:2 + 1:3: longer object length is not a multiple of shorter object
#> length
captured
#> [1] ":> 1:2 + 1:3" "[1] 2 4 4\n"
Only the prompt is changed to :>
. You can use that
content, or print it somewhere, for instance:
The parse_text()
function parse one or more character
strings exactly as if they were commands entered at the R prompt:
… and for an incomplete expression:
The source_clipboard()
source code directly from the
clipboard. All these functions form the basis to simulate an R console
in a different context (a console widget in your own GUI). You can
combine this with to_rjson()
/eval_rjson
to
encode and decode R objects on both sides of a pipeline between the R
process and your GUI.
Rjson is a version of JSON that allows to encore
and decode rapidly almost all R objects. From the example at
?to_rjson
:
# A complex R object
# Note: we round doubles to 14 digits because precision is lost in the process
obj <- structure(list(
a = as.double(c(1:5, 6)),
LETTERS,
c = c(c1 = 4.5, c2 = 7.8, c3 = Inf, c4 = -Inf, NA, c6 = NaN),
c(TRUE, FALSE, NA),
e = factor(c("a", "b", "a")),
f = 'this is a "string" with quote',
g = matrix(round(rnorm(4), 14), ncol = 2),
`h&$@` = list(x = 1:3, y = round(rnorm(3), 14),
fact = factor(c("b", "a", "b"))),
i = Sys.Date(),
j = list(1:5, y = "another item")),
comment = "My comment",
anAttrib = 1:10,
anotherAttrib = list(TRUE, y = 1:4))
# Convert to RJSON
(rjson1 <- to_rjson(obj, attributes = TRUE))
#> [1] list("Data_" := list("a" := c(1., 2., 3., 4., 5., 6.), "" := c("A",
#> [2] "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N",
#> [3] "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"),
#> [4] "c" := c(c1 = 4.5, c2 = 7.8, c3 = Inf, c4 = -Inf,
#> [5] NA, c6 = NaN), "" := c(TRUE, FALSE, NA), "e" := list("Data_" := c(1,
#> [6] 2, 1), "levels" := c("a", "b"), "class" := "factor"),
#> [7] "f" := "this is a \\"string\\" with quote", "g" := list("Data_" := c(-1.35251305957203,
#> [8] -0.3715069788267, 0.8298054127599, 0.76527377860721), "dim" := c(2,
#> [9] 2)), "h&$@" := list("x" := seq(1, 3), "y" := c(1.07476635239398,
#> [10] 0.9099224792409, -0.67902228603092), "fact" := list("Data_" := c(2,
#> [11] 1, 2), "levels" := c("a", "b"), "class" := "factor")),
#> [12] "i" := list("Data_" := 20021., "class" := "Date"),
#> [13] "j" := list("" := seq(1, 5), "y" := "another item")), "comment" := "My comment", "anAttrib" := seq(1, 10), "anotherAttrib" := list(
#> [14] "" := TRUE, "y" := seq(1, 4)))
# Get back an R object from Rjson
(obj2 <- eval_rjson(rjson1))
#> $a
#> [1] 1 2 3 4 5 6
#>
#> [[2]]
#> [1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
#> [20] "T" "U" "V" "W" "X" "Y" "Z"
#>
#> $c
#> c1 c2 c3 c4 c6
#> 4.5 7.8 Inf -Inf NA NaN
#>
#> [[4]]
#> [1] TRUE FALSE NA
#>
#> $e
#> [1] a b a
#> Levels: a b
#>
#> $f
#> [1] "this is a \"string\" with quote"
#>
#> $g
#> [,1] [,2]
#> [1,] -1.352513 0.8298054
#> [2,] -0.371507 0.7652738
#>
#> $`h&$@`
#> $`h&$@`$x
#> [1] 1 2 3
#>
#> $`h&$@`$y
#> [1] 1.0747664 0.9099225 -0.6790223
#>
#> $`h&$@`$fact
#> [1] b a b
#> Levels: a b
#>
#>
#> $i
#> [1] "2024-10-25"
#>
#> $j
#> $j[[1]]
#> [1] 1 2 3 4 5
#>
#> $j$y
#> [1] "another item"
#>
#>
#> attr(,"anAttrib")
#> [1] 1 2 3 4 5 6 7 8 9 10
#> attr(,"anotherAttrib")
#> attr(,"anotherAttrib")[[1]]
#> [1] TRUE
#>
#> attr(,"anotherAttrib")$y
#> [1] 1 2 3 4
# Is it identical to obj?
identical(obj, obj2)
#> [1] TRUE
There are several different functions in R to access system files, or
files inside R packages: R.home()
,
system.file()
, Sys.which()
,
tempdir()
. The system_dir()
and
system_file()
functions centralize their functionalities.
For instance:
system_file("help", "AnIndex", package = "splines")
#> [1] "/usr/lib/R/library/splines/help/AnIndex"
There are other possibilities. See ?system_dir
. You may
also be interested by file_edit()
that allows to create and
edit a text file from a template.
compare_r_version()
conveniently compares the current R
version with a specified one. It returns 1 if it is newer, 0, if it is
equal and -1 if it is older.is_win() # Windows?
#> [1] FALSE
is_mac() # MacOS?
#> [1] FALSE
is_rgui() # Is it RGui under Windows?
#> [1] FALSE
is_sdi() # Is RGui run in SDI mode (separate windows)?
#> [1] FALSE
is_rstudio() # Is it RStudio?
#> [1] FALSE
is_rstudio_desktop() # RStudio desktop?
#> [1] FALSE
is_rstudio_server() # RStudio server?
#> [1] FALSE
is_jgr() # Is R running under JGR?
#> [1] FALSE
def()
:args()
(see
?arg_tips
for other functions to get short textual
information about functions):args_tip("ls")
#> [1] "ls(name, pos = -1L, envir = as.environment(pos), all.names = FALSE, pattern,\n sorted = TRUE)"
TempEnv()
and the temp_XXX()
functions. The
temporary_environment vignette gives more details on
this series of functions.search()
#> [1] ".GlobalEnv" "package:svMisc" "package:rmarkdown"
#> [4] "package:stats" "package:graphics" "package:grDevices"
#> [7] "package:utils" "package:datasets" "package:methods"
#> [10] "SciViews:TempEnv" "Autoloads" "package:base"
# Assign a variable in a temporary environment
assign_temp("my_var", 1:5)
# The environment is named SciViews:TempEnv
search()
#> [1] ".GlobalEnv" "package:svMisc" "package:rmarkdown"
#> [4] "package:stats" "package:graphics" "package:grDevices"
#> [7] "package:utils" "package:datasets" "package:methods"
#> [10] "SciViews:TempEnv" "Autoloads" "package:base"
# Get the variable
get_temp("my_var")
#> [1] 1 2 3 4 5
# List variables in the temporary environment
ls(envir = TempEnv())
#> [1] "my_var"
# Delete the variable
rm_temp("my_var")
The list of missing packages is written in a variable
named .packages_to_install
located in the
SciViews:TempEnv
environment↩︎