I have these files in my global environment:
x <- sapply(sapply(ls(), get), is.data.frame)
n = names(x)[(x==TRUE)]
n
[1] "sample_1" "sample_10" "sample_2" "sample_3" "sample_4" "sample_5" "sample_6" "sample_7" "sample_8" "sample_9" "table_i"
I want to remove all files that start with "samp". I found the this code that can do this (How do I clear only a few specific objects from the workspace?):
rm(list = apropos("samp_"))
Now, I want to learn how to do the same thing using a different way. I found another way to find out all files in the global environment that start with "samp":
nn = grep("samp", n, value = TRUE)
[1] "sample_1" "sample_10" "sample_2" "sample_3" "sample_4" "sample_5" "sample_6" "sample_7" "sample_8" "sample_9"
Then, I tried to delete these files:
for (file in nn){
nn[i] <- NULL
}
do.call(file.remove, list(nn))
I think I am missing something here - can someone please show me how to correct this?
Thank you!
You can make use of pattern inside of the remove function:
rm(list = ls(pattern = "^samp"))
Or using grep:
rm(list = grep("^samp", ls(), value = TRUE))
Related
How can I write a generic R function that cleans the current workspace apart from some self-defined variables? For sure, I can achieve this in a single script with the following code:
prj = '/path/to/project'
src = 'string'
data_to_clean = head(iris)
rm(list = ls()[ !ls() %in% c('prj', 'src') ] )
# only prj and src remain
However I want this to be a function, so that it's applicable for multiple scripts and I can change the variables which should not be cleaned, in one place. Is this possible?
In case you wrap this in a function, you have to keep in mind, that a function will create its own environment, when executed. Therefore, you need to specify the environment every time (in each ls as well as rm). You probably want to remove them from the .GlobalEnv.
clean_workspace <- function(not_to_be_removed) {
rm(list =
setdiff(ls(envir = .GlobalEnv), c("clean_workspace", not_to_be_removed)),
envir = .GlobalEnv)
}
prj = '/path/to/project'
src = 'string'
data_to_clean = head(iris)
clean_workspace(c('prj', 'src'))
In order not to remove the function itself, it should be added to the values not to be removed.
If you want to read more about environments, have a look a this overview.
I think you want to remove the function itself. The important bit is to tell rm the environment where to remove these objects from:
clean_workspace <- function(not_to_be_removed, envir = globalenv()) {
objs <- ls(envir = envir)
rm(list = objs[ !objs %in% not_to_be_removed], envir = envir)
}
prj = '/path/to/project'
src = 'string'
data_to_clean = head(iris)
clean_workspace(c('prj', 'src'))
ls()
#> [1] "prj" "src"
It's obviously not something to advise in an ideal workflow but sometimes it can be useful.
Can it be done easily ?
I made the following functions, it will put a temp file in your home folder and delete it when it's fetched by default :
shoot <- function(..., list = character(), rm = FALSE){
path <- file.path(path.expand("~"),"temp_object.RData")
save(..., list = list, file = path)
if(rm) rm(list = c(list,as.character(substitute(alist(...))[-1])),
envir = parent.frame())
invisible(NULL)
}
loot <- function(rm = TRUE){
path <- file.path(path.expand("~"),"temp_object.RData")
if(file.exists(path)){
load(path,envir = parent.frame())
if(rm) file.remove(path)
} else {
stop("nothing to loot!")
}
invisible(NULL)
}
test <- "abcd"
shoot(test)
rm(test)
loot() # in practice from another session
test
# [1] "abcd"
Useful in my case if one RStudio session has a bug and I can't plot, so I can send it to another.
With a simple change in the default path can be used in a network to easily pass data between colleagues for example.
Thanks to #MrFlick for suggestions
One of the powers of R / Shiny is the posiblity to "source" a other R file in the R code. I am doing this dynamicly so in the end there are a lot of sourced files. So far so good.
FileToSource <- paste("Folder/",df$filename,".R", sep = "")
source(FileToSource, chdir=T)
unsource(......) ???
But at some point i want to clean up. I can delete variables etc. but can i "unsource" the previously "sourced" files ?
I have been looking for code of a way to do this but no luck up till now.
You can wonder if it is nessesary to "unsource" files but i like to clean up once in a while and this can be part of it. Less chance of conflicting code etc...
Suggestions ?
Thanks in advance, if i find a way i'll post it here too
You might want to consider using a local environment. Let's say there is a file called ~/x.R that contains one line bb <- 10. You can create a new environment
envir <- new.env()
and then source the file in that environment by
source('~/x.R',local=envir)
Then, you will be able to obtain the value of bb as envir$bb, and you wouldn't see bb in your Global Environment. Afterwards, you can delete the environment envir by setting envir <- NULL or something like that.
Great i did this test to find out if/how it works:
A.R:
xx <- function(){
print("A print")
}
yy <- 11
B.R:
xx <- function(){
print("B print")
}
yy <- 99
Main.R:
(remove the # to get a Error : attempt to apply non-function)
A <- new.env()
B <- new.env()
source("A.R", local=A)
source("B.R", local=B)
A$xx()
print(A$yy)
B$xx()
print(B$yy)
A <- NULL
#A$xx()
#print(A$yy)
B$xx()
print(B$yy)
B <- NULL
#A$xx()
#print(A$yy)
#B$xx()
#print(B$yy)
So in the end Main.R is
EMPTY & CLEAN & TIDY
<< just wat i wanted ! >>
THANKS #MARAT
First, please note that the following code creates and removes a folder in the current directory. If it conflicts with any of your file names, don't run this code. I'm not sure how to explain this question without it.
In fun1 I use on.exit(..., add = TRUE) on one line, and on the next I try to remove the directory I created with another on.exit call. It doesn't work.
fun1 <- function(){
if(!file.exists("Rsaber")) dir.create("Rsaber")
on.exit(file.remove(paste0("Rsaber/", list.files("Rsaber"))), add = TRUE)
on.exit(file.remove("Rsaber"))
write.csv("1,2,3,4", file = "Rsaber/new.csv")
}
> fun1()
# Warning message:
# In file.remove("Rsaber") :
# cannot remove file 'Rsaber', reason 'Directory not empty'
> file.exists("Rsaber")
# [1] TRUE
> list.files("Rsaber")
# [1] "new.csv"
However, this method works.
fun2 <- function(){
if(!file.exists("Rsaber")) dir.create("Rsaber")
on.exit(file.remove(c(paste0("Rsaber/", list.files("Rsaber"))), "Rsaber"))
write.csv("1,2,3,4", file = "Rsaber/new.csv")
}
> fun2()
> file.exists("Rsaber")
# [1] FALSE
This second method is also much cleaner and probably the way to go, but
Why doesn't on.exit(..., add = TRUE) behave as expected in fun1 ?
Note that I'm not using a temporary directory here because this is part of a larger function that has a logical argument for determining whether or not to keep a downloaded data file.
System info:
> version[[1]]
# [1] "x86_64-pc-linux-gnu"
I think you need add=TRUE on the second file.remove otherwise the second statement replaces the first:
fun1 <- function(){
if(!file.exists("Rsaber")) dir.create("Rsaber")
on.exit(file.remove(paste0("Rsaber/", list.files("Rsaber"))))
on.exit(file.remove("Rsaber"), add = TRUE)
write.csv("1,2,3,4", file = "Rsaber/new.csv")
}
Also as noted this wont work on windows as the directory will not be considered as a file.
For cross-platform support maybe consider unlink
fun1 <- function(){
if(!file.exists("Rsaber")) dir.create("Rsaber")
on.exit(unlink("Rsaber", recursive = TRUE))
write.csv("1,2,3,4", file = "Rsaber/new.csv")
print(system('ls'))
}
I have a small R script of 14 functions and want to run it for 81 files. While I have read several posts on Stack Overflow that address similar issues, I am still having trouble getting this working. I am using a for loop and rbind.
All functions within the { } of the loop work. I have tested them without the for loop and I get the vector of data that I need. But when I run the for loop I only get an output for the last file in the folder. I am not sure what is going on.
Is the for loop working right (is it iterating through the files) and simply overwriting the previous runs? If the for loop is working then I assume I have a problem with my rbind. Or, is the for loop only running the last file in list.files()?
In the end, I want a matrix (or table) with the results of the 14 functions for each of the 81 files.
Here is the code:
res=(1:14)
for(i in list.files())
{
nd = read.csv(i, header= TRUE, row.names =1, check.names = FALSE)
mx = as.matrix(nd)
res[1]=basename(i)
res[2]=-99 #this is just a place holder
res[3]=gden(mx)
res[4]=centralization(mx,degree)
deg = degree(mx, gmode="graph", diag=FALSE, rescale=FALSE)
res[5]=mean(deg)
res[6]=sd(deg)
res[7]=max(deg)
res[8]=min(deg)
Ndeg = degree(mx, gmode="graph", diag=FALSE, rescale=TRUE)*1000
res[9]=mean(Ndeg)
res[10]=sd(Ndeg)
res[11]=max(Ndeg)
res[12]=min(Ndeg)
iso = isolates(mx, diag=FALSE)
res[13]=length(iso)
res[14]=nrow(mx)
}
results=rbind(res)
results
Make your set of functions together a new function and sapply it to every element of list.files():
out <- sapply(list.files(), function(i){
nd = read.csv(i, header= TRUE, row.names =1, check.names = FALSE)
mx = as.matrix(nd)
res = numeric(14)
res[1]=basename(i)
res[2]=-99 #this is just a place holder
res[3]=gden(mx)
res[4]=centralization(mx,degree)
deg = degree(mx, gmode="graph", diag=FALSE, rescale=FALSE)
res[5]=mean(deg)
res[6]=sd(deg)
res[7]=max(deg)
res[8]=min(deg)
Ndeg = degree(mx, gmode="graph", diag=FALSE, rescale=TRUE)*1000
res[9]=mean(Ndeg)
res[10]=sd(Ndeg)
res[11]=max(Ndeg)
res[12]=min(Ndeg)
iso = isolates(mx, diag=FALSE)
res[13]=length(iso)
res[14]=nrow(mx)
return(res)
}
out
you have to have rbind(res) inside the loop,something like this
results = rbind(res), but that is not enough. something like results = rbind(results,res)
It depends how you want to store them as an array of array etc..
You'd better also lapply sapply etc.. instead of loop
I also posted this question on my university listserv and a fellow student provided the following fixes. And now it works :)
res=(1:14)
summary=(1:14)
for(i in list.files())
{
....code as above.....
summary=rbind(summary, res)
}
summary
# then to put into a .csv
write.csv(summary, "nameoffile.csv")