From remove all variables except functions, I got the command to remove all variables without removing functions. I don't want to type it in all the time, so I tried to turn it into a function defined in ~/.Rprofile. I'm new to R, but I've browsed the environment frame scheme, and have a shaky understanding of it. The following attempt doesn't seem to erase a time series object defined in the main environment (the command line prompt when I first start R):
# In ~/.Rprofile
clVar <- function()
{
rm(
list=setdiff( ls(all.names=TRUE), lsf.str(all.names=TRUE)),
envir=parent.frame()
)
}
The following code shows that it doesn't work:
( x<-ts( 1:100 ,frequency=12 ) )
clVar()
ls()
Thanks for any help in fixing the environment framing.
You need to pass the parent.frame() environment to ls, not just to rm. Otherwise ls won't find the variables to remove.
clVar <- function()
{
env <- parent.frame()
rm(
list = setdiff( ls(all.names=TRUE, env = env), lsf.str(all.names=TRUE, env = env)),
envir = env
)
}
Related
I am trying to write an R-script that uses nested functions to save multiple data.frames (parallelly) to global environment. The below sample code works fine in Windows. But when I moved the same code to a Linux server, the objects the function - prepare_output() saves to global environment are not captured by the save() operation in function - get_output().
Am i missing something that is fundamentally different on how mcmapply affects scoping in Linux vs Windows?
library(data.table)
library(parallel)
#Function definitions
default_case <- function(flag){
if(flag == 1){
create_input()
get_output()
}else{
Print("select a proper flag!")
}
}
create_input <- function(){
dt_initial <<- data.table('col1' = c(1:20), 'col2' = c(21:40)) #Assignment to global envir
}
get_output<- function(){
list1 <- c(5,6,7,8)
dt1 <- data.table(dt_initial[1:15,])
prepare_output<- function(cnt){
dt_new <- data.table(dt1)
dt_new <- dt_new[col1 <= cnt, ]
assign(paste0('dt_final_',cnt), dt_new, envir = .GlobalEnv )
#eval(call("<<-",paste0('dt_final_',cnt), dt_new))
print('contents in global envir inside:')
print(ls(name = .GlobalEnv)) # This print all object names dt_final_5 through dt_final_8 correctly
}
mcmapply(FUN = prepare_output,list1,mc.cores = globalenv()$numCores)
print('contents in global envir outside:')
print(ls(name = .GlobalEnv)) #this does NOT print dataframes generated and assigned to global in function prepare_output
save( list = ls(name = .GlobalEnv)[ls(name = .GlobalEnv) %like% 'dt_final_' ], file = 'dt_final.Rdata')
}
if(Sys.info()['sysname'] == "Windows"){numCores <- 1}else{numCores <- parallel::detectCores()}
print('numCores:')
print(numCores)
#Function call
default_case(1)
The reason I an using nested structure is because the preparation of dt1 is time taking and I do not want to increase the execution time by its execution every loop in the apply call.
(Sorry, I'll write this as an 'Answer' because the comment box is too brief)
The best solution to your problem would be to make sure you return the objects you produce rather than trying to assign them from inside a function to an external environment [edit 2020-01-26] which never works in parallel processing because parallel workers do not have access to the environments of the main R process.
A very good rule of thumb in R that will help you achieve this: Never use assign() or <<- in code - neither for sequential nor for parallel processing. At best, you can get such code to work in sequential mode but, in general, you will end up with hard to maintain and error-prone code.
By focusing on returning values (y <- mclapply(...) in your example), you'll get it right. It also fits in much better with the overall functional design of R and parallelizes more naturally.
I've got a blog post 'Parallelize a For-Loop by Rewriting it as an Lapply Call' from 2019-01-11 that might help you transition to this functional style.
I'm trying to clear my R workspace. Nothing I've found in any thread seems to work - and I've been googling and trying solutions for hours now :(
When I open R and type ls, the console displays all the code from a previous session:
function (name, pos = -1L, envir = as.environment(pos), all.names = FALSE,
pattern)
{
if (!missing(name)) {
nameValue <- try(name, silent = TRUE)
if (identical(class(nameValue), "try-error")) {
name <- substitute(name)
if (!is.character(name))
name <- deparse(name)
warning(gettextf("%s converted to character string",
sQuote(name)), domain = NA)
pos <- name
}
else pos <- nameValue
}
all.names <- .Internal(ls(envir, all.names))
if (!missing(pattern)) {
if ((ll <- length(grep("[", pattern, fixed = TRUE))) &&
ll != length(grep("]", pattern, fixed = TRUE))) {
if (pattern == "[") {
pattern <- "\\["
warning("replaced regular expression pattern '[' by '\\\\['")
}
else if (length(grep("[^\\\\]\\[<-", pattern))) {
pattern <- sub("\\[<-", "\\\\\\[<-", pattern)
warning("replaced '[<-' by '\\\\[<-' in regular expression pattern")
}
}
grep(pattern, all.names, value = TRUE)
}
else all.names
}
<bytecode: 0x2974f38>
<environment: namespace:base>
If I type rm(list=ls()) and then type ls again, I get the exact same response - i.e., the code from the previous session hasn't been removed.
By the way, I'm typing ls without the parentheses. Typing ls() with parentheses returns character(0).
I've also tried clearing the environment via RStudio, and even deleting the ~/.Rdata file. Nothing will clear this workspace. Every time I restart R and type ls, all the old code is still there.
I've already tried the tips in this thread, and they don't work for me.
Any idea why this might be happening? Thanks!
What you are seeing is the source code for the ls function. When you enter a function name without the parentheses, you'll see the complete source code for that function (provided that function is in one of the packages attached to the search path, or in the global environment).
When you see character(0) as the result of calling ls(), that means that there are no objects in the global environment. The base package, where ls calls home, is different from the global environment, and objects there cannot be removed.
When character(0) is the result of ls() after you call rm(list=ls()), you have successfully cleared the objects in the global environment.
How do I create a set of R functions that all access the same private variable?
Let's say I want to create readSetting(key) and writeSetting(key,value) functions that both operate on the same hidden list settings. If I try it like so...
local( {
settings <- list()
readSetting <<- function ( key ) settings[[key]]
writeSetting <<- function ( key, value ) settings[[key]] = value
} )
...then readSetting and writeSetting are not visible outside of the local call. If I want them to be visible there, I have to first assign
readSetting <- writeSetting <- NULL
outside the local call. There must be a better way, because my code isn't DRY if I have to say in two different ways which variables are public.
(The context of this work is that I'm developing an R package, and this code will be in an auxiliary file loaded into the main file via source.)
This question is related to How to limit the scope of the variables used in a script? but the answers there do not solve my problem.
You can simulate somthing like that using R6Class package and the following very rough code:
Privates <- R6Class("Privates",
public=list(
readSetting = function(key) {
private$settings[[key]]
},
writeSetting = function(key,value) {
private$settings[[key]] <<- value
}
),
private=list(
settings = list()
)
)
a <- Privates$new()
a$writeSetting("a",4)
a$readSetting("a")
Directly reading o setting the a$setting would not work.
I'd like to clear the environment during a script run.
I am using of the (slightly changed) function which i've seen here
clearEnv <- function(env = parent.frame())
{
rm(list = setdiff( ls(all.names=TRUE, env = env), lsf.str(all.names=TRUE, env = env)),envir = env)
}
But this only works outside of a script. I want to call this function in-script of my personal R package before anything else is saved as variable.
Is there a way of doing this? Maybe nesting the function somewhere?
Thank you!
EDIT:
Thought it was clear enough - obviously not, so here is a minimal example:
script.R has two functions
clearEnv <- function(env = parent.frame())
{
rm(list = setdiff( ls(all.names=TRUE, env = env), lsf.str(all.names=TRUE, env = env)),envir = env)
}
myScript <- function(){
clearEnv()
/*do work*/
}
-- This does not work. I see that it is not clearing the environment at all, because when I save a variable, say thisShouldVanish <- 0, before running myScript(), it is still there afterwards.
If I run
clearEnv()
myScript()
it is working as expected, but I want to run myScript() only instead of separating the two function calls...
I mentioned, that this functions are part of a package, so neither these function nor anything else has to be in the environment -> it should be okay to delete mid-run.
I hope I was able to explain it better.
I'm trying to clear my R workspace. Nothing I've found in any thread seems to work - and I've been googling and trying solutions for hours now :(
When I open R and type ls, the console displays all the code from a previous session:
function (name, pos = -1L, envir = as.environment(pos), all.names = FALSE,
pattern)
{
if (!missing(name)) {
nameValue <- try(name, silent = TRUE)
if (identical(class(nameValue), "try-error")) {
name <- substitute(name)
if (!is.character(name))
name <- deparse(name)
warning(gettextf("%s converted to character string",
sQuote(name)), domain = NA)
pos <- name
}
else pos <- nameValue
}
all.names <- .Internal(ls(envir, all.names))
if (!missing(pattern)) {
if ((ll <- length(grep("[", pattern, fixed = TRUE))) &&
ll != length(grep("]", pattern, fixed = TRUE))) {
if (pattern == "[") {
pattern <- "\\["
warning("replaced regular expression pattern '[' by '\\\\['")
}
else if (length(grep("[^\\\\]\\[<-", pattern))) {
pattern <- sub("\\[<-", "\\\\\\[<-", pattern)
warning("replaced '[<-' by '\\\\[<-' in regular expression pattern")
}
}
grep(pattern, all.names, value = TRUE)
}
else all.names
}
<bytecode: 0x2974f38>
<environment: namespace:base>
If I type rm(list=ls()) and then type ls again, I get the exact same response - i.e., the code from the previous session hasn't been removed.
By the way, I'm typing ls without the parentheses. Typing ls() with parentheses returns character(0).
I've also tried clearing the environment via RStudio, and even deleting the ~/.Rdata file. Nothing will clear this workspace. Every time I restart R and type ls, all the old code is still there.
I've already tried the tips in this thread, and they don't work for me.
Any idea why this might be happening? Thanks!
What you are seeing is the source code for the ls function. When you enter a function name without the parentheses, you'll see the complete source code for that function (provided that function is in one of the packages attached to the search path, or in the global environment).
When you see character(0) as the result of calling ls(), that means that there are no objects in the global environment. The base package, where ls calls home, is different from the global environment, and objects there cannot be removed.
When character(0) is the result of ls() after you call rm(list=ls()), you have successfully cleared the objects in the global environment.