I want to put the following function in my .Rprofile to make installation of bioconductor packages easier:
install.bioconductor <- function(...) {
source("http://bioconductor.org/biocLite.R")
biocLite(...)
}
But when I load a new R session, this function is now listed when I call ls. Is there a way of masking the function from being shown?
You can put it in its own environment and attach that environment to the search path.
myFUNs <- new.env()
myFUNs$install.bioconductor <- function(...) {
source("http://bioconductor.org/biocLite.R")
biocLite(...)
}
attach(myFUNs) # attach to the search path
rm(myFUNs) # remove from .GlobalEnv
# it is still accessible via
# install.bioconductor(...)
Then it be accessible, but will not show up in ls(). (You can see what is attached to the search path with search(), and you can see what is in myFUNs with ls(myFUNs))
Alternatively, as #JoshuaO'Brien mentioned in a comment you can keep it in the .GlobalEnv but add a dot to the beginning of the name (i.e. name it .install.bioconductor) so that it will be "hidden" such that it won't show up with ls(), but will show up with ls(all.names=TRUE).
Related
In an R package, let's say we have two functions. One is setting some parameters; the other one is using those parameters. How can I build such a pattern in R. It is similar to event-driven applications. But I am not sure if it is possible in R or not.
For example:
If we run set_param( a=10), whenever we run print_a.R, it prints 10, and incase of running set_param(a=20), it prints 20.
I need a solution without assigning value to the global environment because CRAN checks raise notes.
I suggest adding a variable to your package, as #MrFlick suggested.
For instance, in ./R/myoptions.R:
.myoptions <- new.env(parent = emptyenv())
getter <- function(k) {
.myoptions[[k]]
}
setter <- function(k, v) {
.myoptions[[k]] <- v
}
lister <- function() {
names(.myoptions)
}
Then other package functions can use this as a key/value store:
getter("optA")
# NULL
setter("optA", 99)
getter("optA")
# [1] 99
lister()
# [1] "optA"
and all the while, nothing is in the .GlobalEnv:
ls(all.names = TRUE)
# character(0)
Values can be as complex as you want.
Note that these are not exported, so if you want/need the user to have direct access to this, then you'll need to update NAMESPACE or, if using roxygen2, add #' #export before each function definition.
NB: I should add that a more canonical approach might be to use options(.) for these, so that users can preemptively control and have access to them., programmatically.
Within a package I intend to submit to CRAN, I am using .onload(...) to create a new environment in which needed variables will be stored without directly modifying the global environment.
.onLoad <- function(...) {
envr <- new.env() # when package is loaded, create new environment to store needed variables
}
This function is saved in a file called zzz.R.
I then use assign(...) to assign variables to the new environment:
assign("x", x, envir = envr)
To retrieve variables in the new environment within my created functions, I do
envr$x
However, on building, installing, loading my package, and running my main function, I receive an error that the object 'envr' cannot be found.
I'm wondering what's happening here.
Creating a new environment directly in R works fine:
envr <- new.env()
envr$a <- 5
envr$a
[1] 5
Any thoughts on resolving the issue?
Your code
envr <- new.env()
assigns the new environment to a local variable in the .onLoad function. When that function exits, the variable isn't visible anywhere else.
You can make your assignment outside the function using <<-, but you have to be careful. That makes R look up through enclosing environments until it finds the variable. If it never finds it, it will do the assignment in the global environment, and that's not yours to write in, so CRAN won't accept your package.
So the right way to do this is to create the variable outside any function as suggested in https://stackoverflow.com/a/12605694/2372064, or to create a variable outside the function but create the environment on loading, e.g.
envr <- NULL
.onLoad <- function(...) {
envr <<- new.env() # when package is loaded, create new environment to store needed variables
}
My R script has evolved over many months with many additions and subtractions. It is long and rambling and I would like to find out which packages I am actually using in the code so I can start deleting library() references. Is there a way of finding redundant dependencies in my R script?
I saw this question so I tried:
library(mvbutils)
library(MyPackage)
library(dplyr)
foodweb( funs=find.funs( asNamespace( 'EndoMineR')), where=
asNamespace( 'EndoMineR'), prune='filter')
But that really tells me where I am using a function from a package whereas I don't necessarily remember which functions I have used from which package.
I tried packrat but this is looking for projects whereas mine is a directory of scripts I am trying to build into a package.
To do this you first parse your file and then use getAnywhere to check for each terminal token in which namespace it is defined. Compare the result with the searchpath and you will have the answer. I compiled a function that takes a filename as argument and returns the packages which are used in the file. Note that it can only find packages that are loaded when the function is executed, so be sure to load all "candidates" first.
findUsedPackages <- function(sourcefile) {
## get parse tree
parse_data <- getParseData(parse(sourcefile))
## extract terminal tokens
terminal_tokens <- parse_data[parse_data$terminal == TRUE, "text"]
## get loaded packages/namespaces
search_path <- search()
## helper function to find the package a token belongs to
findPackage <- function(token) {
## get info where the token is defined
token_info <- getAnywhere(token)
##return the package the comes first in the search path
token_info$where[which.min(match(token_info$where, search_path))]
}
packages <- lapply(unique(terminal_tokens), findPackage)
##remove elements that do not belong to a loaded namespace
packages <- packages[sapply(packages, length) > 0]
packages <- do.call(c, packages)
packages <- unique(packages)
##do not return base and .GlobalEnv
packages[-which(packages %in% c("package:base", ".GlobalEnv"))]
}
I have a .Rprofile I have copied from https://www.r-bloggers.com/fun-with-rprofile-and-customizing-r-startup/ However, when I load my R session the functions that are in env$ they don't work and the functions not in env works perfectly, here is an example:
sshhh <- function(a.package){
suppressWarnings(suppressPackageStartupMessages(
library(a.package, character.only=TRUE)))
}
auto.loads <-c("dplyr", "ggplot2")
if(interactive()){
invisible(sapply(auto.loads, sshhh))
}
.env <- new.env()
attach(.env)
.env$unrowname <- function(x) {
rownames(x) <- NULL
x
}
.env$unfactor <- function(df){
id <- sapply(df, is.factor)
df[id] <- lapply(df[id], as.character)
df
}
message("n*** Successfully loaded .Rprofile ***n")
Once R is loaded I can type sshhh and it shows the function, but if I type unfactor it shows object not found
Any help? Should I put all the functions on my workspace???
They functions created in a separate environment are intentionally hidden. This is to protect them from calls to rm(list=ls()).
From the original article:
[Lines 58-59]: This creates a new hidden namespace that we can store
some functions in. We need to do this in order for these functions to
survive a call to “rm(list=ls())” which will remove everything in the
current namespace. This is described wonderfully in this blog post [1].
To use the unfactor function, you would call .env$unfactor().
If you want to make those function available in the global namespace without having to refer to .env, you can simply leave out the whole .env part and just add the function the same way you did for the sshhh function.
[1] http://gettinggeneticsdone.blogspot.com.es/2013/07/customize-rprofile.html
I am compiling a package using roxygen2. I would like to be able to make sure that there no function is defined twice with the same name. However, currently roxygenise() builds the package without issuing a warning.
E.g.
library(roxygen2)
#' Real function
real_function <- function(){print("hello world")}
#' Fake function
real_function <- function(){}
Calling roxygenise() leads to the second definition being used.
I don't think roxygenise can or should do this. If you want to check yourself for duplicate names, you can e.g. run through the files in a directory and attach each file sequentially. The attach function has a warn.conflicts argument that is TRUE by default.
check_duplicate_names <- function(dir){
files <- list.files(dir)
for (file in file.path(dir, files)){
duplicate_test_env <- new.env()
sys.source(file, envir = duplicate_test_env)
attach(duplicate_test_env)
}
for (i in seq_along(files)){
detach(duplicate_test_env)
}
}
check_duplicate_names("path-to-package/R")
Note that if you have duplicate functions within one file this will not work.