Assigning and removing objects in a loop: eval(parse(paste(
That's a pretty disgusting and frustrating way to go about it. Use assign
to assign and rm
's list argument to remove objects.
> for (i in 1:length(x[1,1,])) {
+ assign(letters[i],mean(x[,,i]))
+ }
> ls()
[1] "a" "b" "c" "i" "x"
> a
[1] 3.5
> b
[1] 9.5
> c
[1] 15.5
> for (i in 1:length(x[1,1,])) {
+ rm(list=letters[i])
+ }
> ls()
[1] "i" "x"
>
Whenever you feel the need to use parse
, remember fortune(106):
If the answer is parse() you should
usually rethink the question.
-- Thomas Lumley, R-help (February 2005)
Loading and removing datasets using paste in R
The list
argument of rm
should do what you want. It takes character
of variable names which are removed. So, something like this should work:
for (i in 1:n) {
loaded <- load(paste0("C", i, ".R"))
# do stuff to dataset
rm(list = loaded)
}
Note, that the load
function returns a character
with the names of the loaded object(s). So we can use that when removing the loaded object(s) again. The loaded object(s) with load
does not nessesarily correspond to the filename.
How can I assign a function to a variable that its name should be made by paste function?
This is FAQ 7.21. The most important part of that FAQ is the last part that says not to do it that way, but to put everything into a list and operate on the list.
You can put your objects into a list using code like:
mylists <- lapply( 1:10, function(i) get( paste0('list',i) ) )
Then you can do the replacement with code like:
mylists <- lapply( mylists, function(x) { x[[1]] <- FUN()
x} )
Now if you want to save all the lists, or delete all the lists, you just have a single object that you need to work with instead of looping through the names again. If you want to do something else to each list then you just use lapply or sapply on the overall list in a single easy step without worrying about the loop. You can name the elements of the list to match the original names if you want and access them that way as well. Keeping everything of interest in a single list will also make your code safer, much less likely to accidentilly overwrite or delete another object.
How to modify a certain row of a matrix, which has to be called by paste()
Consider saving all objects into a list using lapply
especially since they are the same structure. With this approach, you avoid millions of matrices flooding your global environment becoming a management headache! Plus, you can easily run the same operations like the rth row across all matrix elements. Additionally, you avoid nested for
loops or using assign
and get
and eval(parse(paste...)))
. And then you still can get those million objects from list, using list2env
:
# LIST OF A MILLION MATRICES (SAME DIMS)
matlist <- lapply(seq(1000000), function(i) matrix(ncol=10, nrow=4))
# NAMING LIST ITEMS
itemnames <- paste0("XY", c(outer(seq(1000), seq(1000), paste0)))
matlist <- setNames(matlist, itemnames)
# UPDATING MATRIX
matlist <- setNames(lapply(seq(length(matlist)), function(i){
mat <- matlist[[i]]
for (r in seq(4)) {
mat[r,] <- some_function(i,r)
}
return(mat)
}), itemnames)
# OUTPUT INDIVIDUAL ELEMENTS TO SEPARATE GLOBAL OBJECTS
list2env(matlist, envir=.GlobalEnv)
At a basic level, what does eval-parse do in R?
eval(parse(text = "Larry"))
is the same as typing Larry
directly into your R terminal.
> "Text"
[1] "Text"
> eval(parse(text = "Text"))
Error in eval(expr, envir, enclos) : object 'Text' not found
> Text = 1:10
> eval(parse(text = "Text"))
[1] 1 2 3 4 5 6 7 8 9 10
It essentially allows you to call objects by their name in a character string. It's useful inside functions where you don't know which object you'll need yet, although most experienced R users find that storing data in a list
eliminates most needs for eval(parse(...))
Save object to RData using eval(parse(text=...)))
I think the easiest way to do this is to use
save(list = varName, file = paste0(varName, ".RData"))
It saves having to get
(or mget
) the variable(s), as save
effectively does it for you.
Using eval within a loop
A more R-like way to do this avoiding the assign/eval would be
DF <- data.frame(
x = c(1,2,3,4,5),
y = c(5,4,3,2,1),
y2 = c(1,2,3,4,5))
plotlist <- list(
Plot1 = ggplot(DF, aes(x=x, y=y)) +
geom_point(),
Plot2 = ggplot(DF, aes(x=x, y=y2)) +
geom_point()
)
pdf(paste0("Plot", "_Test.pdf"), height =8, width=16)
lapply(plotlist, print)
dev.off()
All your plots here are easily stored in a list that we can just lapply()
over when needed.
The main problem is that ggplot objects won't render until they are print()
ed. When you work in the console, by default the result of the last expression is print()
ed. But when you run a loop, that default print()
ing doesn't happen. That's described in this previous question: R: ggplot does not work if it is inside a for loop although it works outside of it
creating variables in for loops and assigning values
Although @Parfait is totally right and you should prefer using list, here is a possibility to answer your question, using eval
and parse
. But you need to put your index i
at the end of your object name, not in the beginning, to avoid problems:
x = 2
for (i in 1:6){
x <- x + 1
assign(paste0("file_",i), read.xlsx(file.path(path,"Template.xlsx"), sheetIndex = x, colIndex = 1:5, startRow = 6, stringsAsFactors=FALSE)
)
#remove rows where the entire row is NA (do not remove rows that have some values and/or NA, has to be completely NA)
assign(paste0("file_",i),
eval(parse(text = paste0("file_",i))) %>%
filter_all(any_vars(!is.na(.)))
}
You can change filter_at
by filter_all
, as you are selecting all columns. But you could actually do:
for (i in 1:6){
x <- x + 1
assign(paste0("file_",i),
read.xlsx(file.path(path,"Template.xlsx"), sheetIndex = x, colIndex = 1:5, startRow = 6, stringsAsFactors=FALSE) %>%
filter_all(any_vars(!is.na(.)))
)
}
Related Topics
How to Download a Large Binary File with Rcurl *After* Server Authentication
Manually Colouring Plots with 'Scale_Fill_Manual' in Ggplot2 Not Working
Determining Minimum Values in a Vector in R
How to Change Factor Labels into String in a Data Frame
How to Search for a String in One Column in Other Columns of a Data Frame
"Error: Continuous Value Supplied to Discrete Scale" in Default Data Set Example Mtcars and Ggplot2
Two Y Axis in Highcharter in R
How to Place an Image in an R Shiny Title
Forest Plot with Table Ggplot Coding
Refer to Range of Columns by Name in R
Plot Only One Side/Half of the Violin Plot
Why Should Someone Use {} for Initializing an Empty Object in R
Re- Installing R Linux Ubuntu: Unmet Dependencies R
Math of Tm::Findassocs How Does This Function Work
Is There a Command Similar to Matlab's "Close All" in R? (How to Close All Graphics Devices)