Assign a value to a variable within a loop in R - r

I need to loop over files and then create for each file an object:
Here is an example :
filenames <- Sys.glob("/Users/Desktop/*.nwk")
for (i in filenames ) {
print(paste0("Processing the phylogeny: ",i))
p <- a code that generate a figure
}
And then I generate 5 figures that I call with this code :
multiplot(p1,p2,p3,p4,p5 ncol=2, labels=c('A', 'B','C','D','E'))
But I wondered how can I call assign the 1,2 etc values into the variable objects p?
I tried to create a nb=1 object and then assign as p+nb <- a code that generate a figure, but it does not work

There are dedicated packages for plotting/merging multiple plots. patchwork, cowplot, grid, egg, etc.
Use lapply to generate ggplot objects in a list, then use cowplot::plot_grid, something like:
cowplot::plot_grid(
plotlist = lapply(list.files(...), function(i){
#import file
d <- read.table(i)
#plot
ggplot(d, aes(...)) + geom_...
}),
ncol = 2)

You can do that but I'll suggest not to create 5 plot objects in global environment. Store the output of plots in a list.
list_plot <- vector('list', length(filenames))
for (i in seq_along(filenames)) {
cat("\nProcessing the phylogeny: ",filenames[i])
list_plot[[i]] <- a code that generate a figure using filenames[i] to read file
}
do.call(multiplot, c(list_plot, ncol=2, labels=c('A', 'B','C','D','E')))

I found a way by doing :
Phylo_name<-paste0("p",nb,sep="")
eval(call("<-", as.name(Phylo_name), ggtree(tr = phylo,
mapping = aes(color = group)) + geom_tiplab() + theme(legend.position="right")+
scale_color_manual(values=color_vector)))

Related

How to create multiple plot from a list which contain List of dataframe in R

until now i am stuck at looping and saving a ggplot from List i have looked at the another question but it did not working.
myplots=list()
par(mfrow = c(1, 5))
for (i in 1:5) {
#name=paste("ggp", i, sep = "_")
p1 =ggplot(Turbine[[i]],
aes(x=Turbine[[i]]$TS,
y=Turbine[[i]]$Pv..turbine))+
geom_point(size=1)+
ggtitle(names(Turbine[i])
)
print(i)
print(p1)
myplots[[i]]= p1
}
multiplot(plotlist=myplots,cols=5)
plot_grid(ggp_1,ggp_2,ggp_3,ggp_4,ggp_5) #trying to save ggplot as variable name
the problem i got is when i want to start plot of multiple plot in 1 drawing. i want to have 5 column of plots.
maybe s lapply func. is good?
let the data be
Turbine=list of listname
first listname= name(Turbine[1])
view(Turbine [[1]])
TS Pv..turbine
1 20
2 20
3 24
4 19
so
Create something like your list:
Turbine = lapply(1:5,data.frame(TS=1:10,"Pv..turbine"=runif(10))
You can use the plotlist= argument in plot_grid, note, you don't need par(mfrow=..)), thats meant for base R plots and also you don't need to use the $ inside aes :
library(cowplot)
library(ggplot2)
myplots=list()
for (i in 1:5) {
myplots[[i]] = ggplot(Turbine[[i]],
aes(x=TS,y=Pv..turbine))+
geom_point(size=1)
}
plot_grid(plotlist=myplots,ncol=5)

(R)Making a list of ggplot objects

My goal it to get a list p which contains two graphs p[[1]] and p[[2]].
p[[1]] and p[[2]] are supposed to be a plot with point(10,10) and point(20,20) for each. But after executing below, in the list p, only p[[2]] shows expected graph. P[[1]] graph does not appear.
How to correct to make p[[1]] in the list have point(10,10)?
(It seemd that the variable cordx and cordy are tightly coupled to p[[1]],
so whenever the cordx, cordy are changed, the alredy made p[[1]] is revised everytime.)
library(ggplot2)
xx<-list(10,20);yy<-list(10,20)
p<-list()
for (i in (1:2) ) {
cordy<-yy[[i]];cordx<-xx[[i]] #But,at 2nd loop(that is when i=2),after executing this line, my p[[1]] is affected unexpectedly, containning point (20,20))
p<-ggplot()+geom_point(aes(x=cordx,y=cordy))
p[[i]]<-p # at 1st loop(that is i=1), p[[1]] contains point (10,10) as expected.
}
print(p[[1]])
print(p[[2]])
May I suggest using mapply() to avoid looping?
Here is the code:
library(ggplot2)
xx <- list(10,20)
yy <- list(10,20)
p <- mapply(function(cordx, cordy) { ggplot() + geom_point(aes(x = cordx, y = cordy)) }, xx, yy, SIMPLIFY = FALSE)
print(p[[1]])
print(p[[2]])
What it does: mapply pass each element of xx and yy in the function that creates the plot. The outputs of the function are stored in the object p. SIMPLIFY = FALSE forces p to be a list.
Outputs:

How do I clear the plot viewer in Rstudio?

I'm saving objects to a list and I'd like to clear the plots pane and viewer pane whenever I load those objects. I basically want the back button to grey out after I've gone through the charts in that element of the list.
This is my code
gg <- ggplot(iris, aes(width, length)) + geom_point
l <- list()
l[["element"]] <- gg
I want it so that when I run l$element, it's like I first clicked the broom on the plots and viewer tab in rstudio.
You can do this as long as you store the ggplot inside a custom S3 class whose default print method calls dev.off then plots the enclosed ggplot:
gg_wipe <- function(x) structure(list(plot = x), class = "gg_wipe")
print.gg_wipe <- function(x) {dev.off(); print(x$plot)}
gg <- ggplot(iris, aes(Sepal.Width, Sepal.Length)) + geom_point()
l <- list()
l[["element"]] <- gg_wipe(gg)
l[["element"]]
Or rather than wrapping the plot as Allan did (which is a good idea) you can provide a helper function and then provide different ways to get at it. So this calls the helper function directly
l <- list(
apple=ggplot(data.frame(x=1:3, y=1:3)) + geom_point(aes(x,y)),
banana=ggplot(data.frame(x=1:3, y=3:1)) + geom_point(aes(x,y))
)
clear_and_print <- function(x, ele) {
graphics.off(); invisible(print(x[[deparse(substitute(ele))]]))
}
clear_and_print(l, apple)
You can define some new operators but they have to be syntactically valid. You can't have ^^^ bur you could have %^%
`%^%` <- clear_and_print
l %^% apple
l %^% banana
Or you can create a special class for your container
`$.plot_clear` <- function(x, ele) {
graphics.off(); x[[ele]]
}
class(l) <- "plot_clear"
l$apple
l$banana

Is it somehow possibe to link a mathematical axis unit expression from a list or dataframe onto an ggplot axis?

I wonder if it's possible to craft a semi-automatic parsing of 'complicated' mathematical expressions into the axis of ggplot by maintaining some sort of lookup table?
So, for example, for data-mining, I regularly have to produce hundreds of scatterplots, which I want to discuss with colleagues. To do so, I want correct axis-legends, of course - this is rather cumbersome.
Here a simple example of what would like to read out from a database into the labs() by using a formula: expression(paste(delta^{18},"O (\u2030)")
So, what I was wondering is if there's a way to link those labs() to predefined lists or tables in a way like labs(y = list[3])?
This works just fine for simple names like: "Dissolved oxygen saturation / %", but when trying the same for the above, it generates:
paste(delta^{
18
}, "O (‰)")
(including the breaks - which is obviously not what I want)
Thanks,
Alex
You could tinker with the math_format() function from the scales package a bit to take in pre-substituted expressions:
library(patchwork)
library(ggplot2)
splitiris <- split(iris, iris$Species)
# Example expressions
exprs <- list(
substitute(10^.x),
substitute(log[.x]~"(%)"),
substitute(frac(.x, 2))
)
# Near-copy of scales::math_format
math_format2 <- function(expr = subsitute(10^.x), format = force) {
.x <- NULL
subs <- function(x) {
do.call("substitute", list(expr, list(.x = x)))
}
function(x) {
x <- format(x)
ret <- lapply(x, subs)
ret <- as.expression(ret)
ret[is.na(x)] <- NA
names(ret) <- names(x)
ret
}
}
# Generate plots
plots <- lapply(seq_along(splitiris), function(i) {
ggplot(splitiris[[i]], aes(Sepal.Width, Sepal.Length)) +
geom_point() +
scale_x_continuous(labels = math_format2(exprs[[i]]))
})
plots[[1]] + plots[[2]] + plots[[3]]
Created on 2020-05-27 by the reprex package (v0.3.0)

Trouble correctly returning object name in for loop

I'm trying to automate making a series of the same plot using different objects; I'm working with S4 class phyloseq objects. When I use a for loop to iterate over a list of objects and try to use the object name as a title for each plot and in a filename for ggsave I can't quite get it to recognize the correct name, though it's making the correct plots for a given object in the list.
I've tried using variations of deparse(substitute(object)) with get() and quote() and end up getting slightly different, but still off-target results.
object_list <- c(object1, object2, object3)
automate_graphs <- function(x){
for(object in x){
name <- deparse(substitute(object))
ordination <- ordinate(object, "NMDS", "bray")
plot <- plot_ordination(object, ordination) + ggtitle(label = name)
ggsave(plot, filename=sprintf("NMDS_bray_%s.pdf", name), height=4, width=7)}}
automate_graphs(object_list)
I'm expecting to save 3 pdfs named NMDS_bray_object1, NMDS_bray_object2, NMDS_bray_object3.
Instead I get NMDS_bray_S4 object of class structure("phyloseq", package = "phyloseq") (so it's saving the deparse of the object to the variable name rather than the substitution) or with quote I get NMDS_bray_object which I suppose is to be expected haha. Thanks in advance for any help!
Just make it a named vector (list) of objects and iterate over the names:
object_list <- c(object1 = object1,object2 = object2,object3 = object3)
automate_graphs <- function(x){
for(nm in names(x)){
object <- x[nm] #Pick out the one named nm
ordination <- ordinate(object, "NMDS", "bray")
plot <- plot_ordination(object, ordination) + ggtitle(label = nm)
ggsave(plot, filename=sprintf("NMDS_bray_%s.pdf", nm), height=4, width=7)
}}
automate_graphs(object_list)
#Joran thanks again for the help--it pushed me in the right direction to figuring out a solution, even if it's not the most elegant. I took the idea of generating a vector of names and then just created an extra variable to cycle through that vector. But this way it maintains the class of object and creates a separate list of corresponding names:
object_list <- c("object1" = object1, "object2" = object2, "object3" = object3)
automate_graphs <- function(x){
names = names(x)
obj_num = 1
for(object in x){
name <- names[obj_num]
ordination <- ordinate(object, "NMDS", "bray")
plot <- plot_ordination(object, ordination) + ggtitle(label = name)
ggsave(plot, filename=sprintf("NMDS_bray_%s.pdf", name), height=4, width=7)
obj_num = obj_num + 1
}
}
automate_graphs(object_list)

Resources