This question already has answers here:
Save multiple ggplots using a for loop
(3 answers)
Closed 2 years ago.
I was wondering if someone could help me get this code to return multiple graphs. I would like each graph to be labelled "plot_i" (plot_G1, plot_G2). I am at a loss as to how to get my function to return this. Any help would be appreciated!
library(lubridate)
library(tidyverse)
#Dummy Data Frame
DateTime <- c("1999/01/01 11:00","1999/01/02 11:00","1999/01/03 11:00","1999/01/01 11:00","1999/01/02 11:00","1999/01/03 11:00","1999/01/01 11:00","1999/01/02 11:00","1999/01/03 11:00")
Step <- c("Condition1","Condition1","Condition1","Condition2","Condition2","Condition2","Condition3","Condition3","Condition3")
G1 <- runif(9)
G2 <- runif(9)
G3 <- runif(9)
G4 <- runif(9)
test_df <- data.frame(DateTime = DateTime, Step = Step, G1 = G1, G2 = G2, G3 = G3, G4 = G4)
test_df$DateTime.lub <- ymd_hm(test_df$DateTime)
test_df
#Want to create a function that will provide graphs for every G1, G2, G3 and G4 and return them!
list <- colnames(test_df)
list <- list[-c(1,2,7)]
list
#test plot - works
ggplot(data = test_df, aes(x= DateTime.lub, y = G1))+
geom_line(aes(size = Step))
#Function does not return graph
for (i in list){
ggplot(data = test_df, aes(x= DateTime.lub, y = i))+
geom_line(aes(colour = Step))
}
Try with this:
library(ggplot2)
#Function does not return graph
for (i in list){
var <- sym(i)
print(ggplot(data = test_df, aes(x= DateTime.lub, y = !!var))+
geom_line(aes(colour = Step))+
ggtitle(paste0('plot_',i)))
}
For anyone else using this, if you want to export graphs see below:
plot_list = list()
for (i in list) {
var <- sym(i)
p = ggplot(test_df, aes(x=DateTime.lub, y=!!var)) +
geom_line(aes(colour=Step))
print(p)
plot_list[[i]] = p
}
setwd("~/WD")
for (i in list) {
file_name = paste("plot_", i, ".tiff", sep="")
tiff(file_name)
print(plot_list[[i]])
dev.off()
}
Related
I have searched in stackoverflow, and there are similar questions, but the answers did not work in my case.
I want to generate a list of plots, and output them in HTML by knitting Rmarkdown file.
Here is a very simple demo code:
library(ggplot2)
library(plotly)
DF <- data.frame(A = c(1:10), B = c(1:10), C = (1:10))
myplots <- vector('list', ncol(DF))
for (i in 1: dim(DF)[2]) {
p = ggplot(DF, aes(x = DF[, i], y = C)) +
geom_point()
myplots[[i]] = plotly::ggplotly(p)
}
myplots[[1]]
myplots[[2]]
myplots[[3]]
If I index them, they can be plotted in HTML file.
myplots[[1]]
myplots[[2]]
myplots[[3]]
However, if I directly use the list object or loop it, none of the method worked:
# method 1
myplots
# method 2
for (i in seq_along(myplots)) print(myplots[[i]])
#nethod 3
for (i in 1:length(myplots)) print(myplots[[i]])
I don't understand the problem. Thanks a lot for your help.
Here is my complete answer, thanks a lot #user2554330
I need to first convert the list into taglist, and then convert it into a plotly htmlwidget object.
library(ggplot2)
library(plotly)
DF <- data.frame(A = c(1:10), B = c(1:10), C = (1:10))
myplots <- htmltools::tagList()
for (i in 1: dim(DF)[2]) {
p = ggplot(DF, aes(x = DF[, i], y = C)) +
geom_point()
myplots[[i]] = plotly::as_widget(plotly::ggplotly(p))
}
myplots
This question already has an answer here:
How to change the chart title dynamically in R?
(1 answer)
Closed 2 years ago.
There is a loop generate the multiple plots.
My question is I want the title name change for each iteration. for example "plot1","plot2","plot3".........
what if I want a sentence for the plot title, say"This is the 1 plot we have","This is the 2 plot we have"
library(tidyverse)
# create a list with a specific length
plot_lst <- vector("list", length = 8)
for (i in 1:8) {
g <- ggplot(data = mtcars, aes(x = hp, y = wt)) +
geom_point()+ggtitle("plot1")
plot_lst[[i]] <- g
}
# Combine all plots
cowplot::plot_grid(plotlist = plot_lst, nrow = 4)
Try this:
library(tidyverse)
# create a list with a specific length
plot_lst <- vector("list", length = 8)
for (i in 1:8) {
g <- ggplot(data = mtcars, aes(x = hp, y = wt)) +
geom_point()+ggtitle(paste0("plot",i))
plot_lst[[i]] <- g
}
# Combine all plots
cowplot::plot_grid(plotlist = plot_lst, nrow = 4)
Output:
I'm having trouble with creating a list of plots using for loops, and I don't know why.
Here's the code that doesn't work (i.e. returns aplotfinal as an empty list)
aplotfinal <- list()
for(i in 1:length(Rlist)){
a <- Rlist[[i]] %>%
select(Frame_times, average)
del <- 0.016667
x.spec <- spectrum(a$average, log = "no", plot = FALSE)
spx <- x.spec$freq/del
spy <- 2*x.spec$spec
aplotfinal[[i]] <- plot(spy~spx, main = names(Rlist)[i], xlab = "frequency", ylab = "spectral density", type = "l")
}
The plot function works, I just want to apply it for a list of dataframes that I have (i.e. Rlist). Thank you!
the base R plot() does not return an object, it just draws on the device. So you have to do a multiplot or save onto a pdf to have a record of the plots.
To store it in a list, I guess you need something like ggplot, for example:
library(ggplot2)
library(gridExtra)
Rlist = lapply(1:5,function(i){
data.frame(Frame_times = seq(0,1,length.out=100),average=runif(100))
})
names(Rlist) = letters[1:5]
aplotfinal <- lapply(1:length(Rlist),function(i){
a <- Rlist[[i]] %>% select(Frame_times, average)
del <- 0.016667
x.spec <- spectrum(a$average, log = "no", plot = FALSE)
spx <- x.spec$freq/del
spy <- 2*x.spec$spec
aplotfinal[[i]] <- qplot(y = spy,x=spx,geom="line") +
ggtitle(names(Rlist)[i]) +
xlab("frequency")+ylab("spectral density")
})
grid.arrange(grobs=aplotfinal,ncol=5)
Here is an example you can use to tweak your code. Plots get saved to the plot_list variable and then to pdf residing at path/to/pdf. Note that you have to initiate a device first (in my case, pdf).
library(ggplot2)
library(dplyr)
df <- data.frame(country = c(rep('USA',20), rep('Canada',20), rep('Mexico',20)),
wave = c(1:20, 1:20, 1:20),
par = c(1:20 + 5*runif(20), 21:40 + 10*runif(20), 1:20 + 15*runif(20)))
countries <- unique(df$country)
plot_list <- list()
i <- 1
for (c in countries){
pl <- ggplot(data = df %>% filter(country == c)) +
geom_point(aes(wave, par), size = 3, color = 'red') +
labs(title = as.character(c), x = 'wave', y = 'value') +
theme_bw(base_size = 16)
plot_list[[i]] <- pl
i <- i + 1
}
pdf('path/to/pdf')
pdf.options(width = 9, height = 7)
for (i in 1:length(plot_list)){
print(plot_list[[i]])
}
dev.off()
I do have a plot_list with almost 300 plots. Is there a way to plot all the plots from the array with plotly? I don't know how to create a subplot with so many plots.
Here is my code:
plot_list = list()
for(i in 2:length(colnames.no.na.work.df.worldbank.2009)){
# Create columns for buffer.data.frame to plot
first.column.buffer <- no.na.work.df.worldbank.2009$`country name`
second.column.buffer <- round(as.numeric(unlist(no.na.work.df.worldbank.2009[134])))
third.column.buffer <- round(as.numeric(unlist(no.na.work.df.worldbank.2009[i])))
colnames.no.na.work.df.worldbank.2009 <- colnames(no.na.work.df.worldbank.2009)
# Create buffer.data.frame to plot
buffer.data.frame <- cbind.data.frame(first.column.buffer, second.column.buffer, third.column.buffer, stringsAsFactors = FALSE)
colnames(buffer.data.frame) <- (c("c", "b", "a"))
# Safe plot in array
p <- ggplot(buffer.data.frame, aes(a, b, name = c)) + ggtitle("Title") + theme(plot.title = element_text(hjust = 0.5)) +
xlab(colnames.no.na.work.df.worldbank.2009[i]) + ylab(colnames.no.na.work.df.worldbank.2009[134]) + geom_point()
plot_list[[i-1]] = p
}
You can put all the items in a list enclosed in divs so you can control style.
Display it using uiOutput()
# You have to provide the plotly plot_list to the function
output$all_plots <- shiny::renderUI({
all_plots <- list()
for (n in seq_along(plot_list)) {
all_plots[[n]] <- div(style="padding:5px; margin: 5px;",plot_list[[n]])
}
return(all_plots)
})
This question already has answers here:
"for" loop only adds the final ggplot layer
(4 answers)
Closed 3 years ago.
Here is reproducible dataframe:
example_df <- data.frame(rnorm1 = rnorm(100),
rnorm2 = rnorm(100),
rnorm3 = rnorm(100),
id = (1:100))
I'd like to plot it in this manner:
plot(example_df[,1], type = 'l')
for(i in 2:3) {
lines(example_df[,i], col = i)
}
But base plot is not convenient for further additions so I want to use ggplot. However, why is it not possible to use the same loop approach?
g1 <- ggplot(example_df, aes(seq(length(example_df[,1]))))
for(i in 1:3) {
g1 <- g1 + geom_line(aes(y=example_df[,i], colour=colnames(example_df)[i]))
}
g1
This only saves the last line:
Now, I can obviously do the same without the loop and it will obviously be incovenient for more than 3 lines:
g2 <- ggplot(example_df, aes(seq(length(example_df[,1]))))
g2 <- g2 + geom_line(aes(y=example_df[,1], colour=colnames(example_df)[1]))
g2 <- g2 + geom_line(aes(y=example_df[,2], colour=colnames(example_df)[2]))
g2 <- g2 + geom_line(aes(y=example_df[,3], colour=colnames(example_df)[3]))
g2
I can also melt the df and get the desired plot:
example_df_melt <- melt(example_df, id.vars = 'id', variable.name = 'variable')
g3 <- ggplot(example_df_melt, aes(id,value)) + geom_line(aes(colour = variable))
g3
But is there any reason for it to not produce the same result in a loop?
Required packages:
require(ggplot2)
require(reshape2)
ggplot is not intended to be used in this way. If you restructure your data slightly, you can avoid using a loop altogether:
example_df <- data.frame(y = c(rnorm(100), rnorm(100), rnorm(100)),
group = rep(c("rnorm1", "rnorm2", "rnorm3"), each = 100),
id = rep((1:100), 3))
ggplot(example_df, aes(y=y, x=id, colour=group))+
geom_line()