How can i plot multiple plots with plotly - r

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)
})

Related

how to change the title name of ggplot in a loop? [duplicate]

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:

Multiple plot in R in a single page

I'm having trouble displaying the multiple graphs on the same page. I'm having a data frame with 18 numerical columns. For each column, I need to show its histogram and boxplot on the same page with a 4*9 grid. Following is what I tried. But I need to show it along with the boxplot as well. Through a for a loop if possible. Can someone please help me to do it.
library(gridExtra)
library(ggplot2)
p <- list()
for(i in 1:18){
x <- my_data[,i]
p[[i]] <- ggplot(gather(x), aes(value)) +
geom_histogram(bins = 10) +
facet_wrap(~key, scales = 'free_x')
}
do.call(grid.arrange,p)
I received the following graph.
When following is tried, I'm getting the graph in separate pages
library(dplyr)
dat2 <- my_data %>% mutate_all(scale)
# Boxplot from the R trees dataset
boxplot(dat2, col = rainbow(ncol(dat2)))
par(mfrow = c(2, 2)) # Set up a 2 x 2 plotting space
# Create the loop.vector (all the columns)
loop.vector <- 1:4
p <- list()
for (i in loop.vector) { # Loop over loop.vector
# store data in column.i as x
x <- my_data[,i]
# Plot histogram of x
p[[i]] <-hist(x,
main = paste("Question", i),
xlab = "Scores",
xlim = c(0, 100))
plot_grid(p, label_size = 12)
}
You can assemble the base R boxplot and the ggplot object generated with facet_wrap together using the R package patchwork:
library(ggplot2)
library(patchwork)
p <- ggplot(mtcars, aes(x = mpg)) +
geom_histogram() +
facet_wrap(~gear)
wrap_elements(~boxplot(split(mtcars$mpg, mtcars$gear))) / p
ggsave('test.png', width = 6, height = 8, units = 'in')

Different colors for facet_grid strip texts in r [duplicate]

I am trying to customize a ggplot2 plot containing facets, and would like to change both the colour of the facet strip, as well as the colour of the font. I found some code to change the strip.background colour, but was not able to modify it to change also the font color... any idea?
What I got so far:
library(ggplot2)
library(grid)
p <- ggplot(mpg, aes(displ, cty)) + geom_point() + facet_grid(drv ~ cyl) +
ggtitle("How to change coloour of font in facet strip?")
g <- ggplot_gtable(ggplot_build(p))
strip_both <- which(grepl('strip-', g$layout$name))
fills <- c("red","green","blue","yellow","red","green","blue","yellow")
k <- 1
for (i in strip_both) {
j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
k <- k+1
}
grid.draw(g)
Created on 2018-11-23 by the reprex package (v0.2.1)
Sure someone could find better solution, but I was only able to do this so far:
library(ggplot2)
library(grid)
library(RColorBrewer)
p <- ggplot(mpg, aes(x = displ, y = cty)) +
geom_point() +
facet_grid(drv ~ cyl) +
ggtitle("How to change coloour of font in facet strip?") +
ggthemes::theme_few()
g <- ggplot_gtable(ggplot_build(p))
strips <- which(grepl('strip-', g$layout$name))
pal <- brewer.pal(8, "Paired")
for (i in seq_along(strips)) {
k <- which(grepl('rect', g$grobs[[strips[i]]]$grobs[[1]]$childrenOrder))
l <- which(grepl('titleGrob', g$grobs[[strips[i]]]$grobs[[1]]$childrenOrder))
g$grobs[[strips[i]]]$grobs[[1]]$children[[k]]$gp$fill <- pal[i]
g$grobs[[strips[i]]]$grobs[[1]]$children[[l]]$children[[1]]$gp$col <- pal[i + 1]
}
plot(g)
Another option is using grid's editing functions, provided that we build the gPath of each grob that we want to edit.
Prepare the gPaths:
library(ggplot2)
library(grid)
p <- ggplot(mpg, aes(displ, cty)) + geom_point() + facet_grid(drv ~ cyl)
# Generate the ggplot2 plot grob
g <- grid.force(ggplotGrob(p))
# Get the names of grobs and their gPaths into a data.frame structure
grobs_df <- do.call(cbind.data.frame, grid.ls(g, print = FALSE))
# Build optimal gPaths that will be later used to identify grobs and edit them
grobs_df$gPath_full <- paste(grobs_df$gPath, grobs_df$name, sep = "::")
grobs_df$gPath_full <- gsub(pattern = "layout::",
replacement = "",
x = grobs_df$gPath_full,
fixed = TRUE)
Check out the table grobs_df and get familiar with the naming and paths. For example all strips contain the key word "strip". Their background is identified by the key word "background" and their title text by "titleGrob" & "text". We can then use regular expression to catch them:
# Get the gPaths of the strip background grobs
strip_bg_gpath <- grobs_df$gPath_full[grepl(pattern = ".*strip\\.background.*",
x = grobs_df$gPath_full)]
strip_bg_gpath[1] # example of a gPath for strip background
## [1] "strip-t-1.7-5-7-5::strip.1-1-1-1::strip.background.x..rect.5374"
# Get the gPaths of the strip titles
strip_txt_gpath <- grobs_df$gPath_full[grepl(pattern = "strip.*titleGrob.*text.*",
x = grobs_df$gPath_full)]
strip_txt_gpath[1] # example of a gPath for strip title
## [1] "strip-t-1.7-5-7-5::strip.1-1-1-1::GRID.titleGrob.5368::GRID.text.5364"
Now we can edit the grobs:
# Generate some color
n_cols <- length(strip_bg_gpath)
fills <- rainbow(n_cols)
txt_colors <- gray(0:n_cols/n_cols)
# Edit the grobs
for (i in 1:length(strip_bg_gpath)){
g <- editGrob(grob = g, gPath = strip_bg_gpath[i], gp = gpar(fill = fills[i]))
g <- editGrob(grob = g, gPath = strip_txt_gpath[i], gp = gpar(col = txt_colors[i]))
}
# Draw the edited plot
grid.newpage(); grid.draw(g)
# Save the edited plot
ggsave("edit_strips_bg_txt.png", g)
Although the question was already answered long ago I've wrapped a function to easily set background, border and text colour of individual facets based on previous answers. I'm posting it in case it is of help to someone else.
library(dplyr)
library(ggplot2)
library(RColorBrewer)
The function:
modify_facet_appearance <- function(plot = NULL,
strip.background.x.fill = NULL,
strip.background.y.fill = NULL,
strip.background.x.col = NULL,
strip.background.y.col = NULL,
strip.text.x.col = NULL,
strip.text.y.col = NULL){
if(is.null(plot)){stop("A ggplot (gg class) needs to be provided!")}
# Generate gtable object to modify the facet strips:
g <- ggplot_gtable(ggplot_build(plot))
# Get the locations of the right and top facets in g:
stripy <- which(grepl('strip-r|strip-l', g$layout$name)) # account for when strip positions are switched r-l and/or t-b in facet_grid(switch = )
stripx <- which(grepl('strip-t|strip-b', g$layout$name))
# Check that the provided value arrays have the same length as strips the plot has:
lx <- c(length(strip.background.x.fill), length(strip.background.x.col), length(strip.text.x.col))
if(!all(lx==length(stripx) | lx==0)){stop("The provided vectors with values need to have the same length and the number of facets in the plot!")}
ly <- c(length(strip.background.y.fill), length(strip.background.y.col), length(strip.text.y.col))
if(!all(ly==length(stripy) | ly==0)){stop("The provided vectors with values need to have the same length and the number of facets in the plot!")}
# Change the strips on the y axis:
for (i in seq_along(stripy)){ # if no strips in the right, the loop will not be executed as seq_along(stripy) will be integer(0)
# Change strip fill and (border) colour :
j1 <- which(grepl('strip.background.y', g$grobs[[stripy[i]]]$grobs[[1]]$childrenOrder))
if(!is.null(strip.background.y.fill[i])){g$grobs[[stripy[i]]]$grobs[[1]]$children[[j1]]$gp$fill <- strip.background.y.fill[i]} # fill
if(!is.null(strip.background.y.col[i])){g$grobs[[stripy[i]]]$grobs[[1]]$children[[j1]]$gp$col <- strip.background.y.col[i]} # border colour
# Change color of text:
j2 <- which(grepl('strip.text.y', g$grobs[[stripy[i]]]$grobs[[1]]$childrenOrder))
if(!is.null(strip.text.y.col[i])){g$grobs[[stripy[i]]]$grobs[[1]]$children[[j2]]$children[[1]]$gp$col <- strip.text.y.col[i]}
}
# Same but for the x axis:
for (i in seq_along(stripx)){
# Change strip fill and (border) colour :
j1 <- which(grepl('strip.background.x', g$grobs[[stripx[i]]]$grobs[[1]]$childrenOrder))
if(!is.null(strip.background.x.fill[i])){g$grobs[[stripx[i]]]$grobs[[1]]$children[[j1]]$gp$fill <- strip.background.x.fill[i]} # fill
if(!is.null(strip.background.x.col[i])){g$grobs[[stripx[i]]]$grobs[[1]]$children[[j1]]$gp$col <- strip.background.x.col[i]} # border colour
# Change color of text:
j2 <- which(grepl('strip.text.x', g$grobs[[stripx[i]]]$grobs[[1]]$childrenOrder))
if(!is.null(strip.text.x.col[i])){g$grobs[[stripx[i]]]$grobs[[1]]$children[[j2]]$children[[1]]$gp$col <- strip.text.x.col[i]}
}
return(g)
# Note that it returns a gtable object. This can be ploted with plot() or grid::draw.grid().
# patchwork can handle the addition of such gtable to a layout with other ggplot objects,
# but be sure to use patchwork::wrap_ggplot_grob(g) for proper alignment of plots!
# See: https://patchwork.data-imaginist.com/reference/wrap_ggplot_grob.html
}
Example:
The function can be piped from a gg object sort of in the same spirit as adding + theme().
pal.y <- brewer.pal(length(unique(mpg$drv))*2, "Paired")
pal.x <- brewer.pal(length(unique(mpg$cyl))*2, "Paired")
p <- {ggplot(mpg, aes(displ, cty)) +
geom_point() +
facet_grid(drv ~ cyl) +
ggtitle("How to change colour of font in facet strip?")} %>%
modify_facet_appearance(strip.background.x.fill = pal.x[seq(1, length(pal.x), 2)],
strip.background.x.col = pal.x[seq(2, length(pal.x), 2)],
strip.text.x.col = pal.x[seq(2, length(pal.x), 2)],
strip.background.y.fill = pal.y[seq(1, length(pal.y), 2)],
strip.background.y.col = pal.y[seq(2, length(pal.y), 2)],
strip.text.y.col = pal.y[seq(2, length(pal.y), 2)])
plot(p)

Generate a multi-page pdf file of a grid of ggplot plots [duplicate]

This question already has answers here:
Plot over multiple pages
(3 answers)
Closed 3 years ago.
I am trying to generate a multi-page pdf of a grid of ggplots from a list of ggplots. I have tried very many ways to do this and have not succeeded. Here is a reproducible equivalent to what I have been working with:
library(ggplot2)
# generate a data frame w same structure as the one I'm working with
time <- c(1:10)
veclist <- list()
veclist[[1]] <- time
for (i in 2:25){
veclist[[i]] <- as.vector(c(runif(10,-2,2)))
}
d <- as.data.frame(do.call(rbind, veclist))
d <- as.data.frame(t(d))
colnames(d)[1] <- "time"
for (i in 2:length(d)){
colnames(d)[i] <- paste("name",i,sep=" ")
}
# for a common axis
numericvalues <- d[,2:length(d)]
# generate plot(s)
name_list = paste("`",names(d),"`",sep="")
plot_list = list()
for (i in 2:length(d)) {
p = ggplot(d, aes_string(x=name_list[[1]], y=name_list[[i]])) +
geom_point() +
labs(x="time",title=paste(strwrap(names(d[i]), width = 30),collapse = "\n")) +
theme(plot.title = element_text(size=10,hjust = 0.5),axis.text.x=element_text(size=6)) +
coord_cartesian(ylim = c(min(numericvalues, na.rm = TRUE), max(numericvalues, na.rm = TRUE)))
plot_list[[i]] = p
}
What I am looking for would generate a multi-page pdf grid of the plots in plot_list (ideally with 3 columns, 4 rows of plots per page).
A few things I have tried:
pdf("test.pdf")
do.call("marrangeGrob",c(plot_list,ncol=3,nrow=2))
produces an unreadable pdf file.
pdf("test.pdf")
do.call("grid.arrange",c(plot_list))
returns only 'grobs' allowed in "gList" error.
This one produces a multipage layout:
library(gridExtra)
...
plot_list = list()
for (i in 2:length(d)) {
p = ggplot(...)
plot_list[[i]] = ggplotGrob(p)
}
class(plot_list) <- c("arrangelist", class(plot_list))
ggsave("multipage.pdf", plot_list)
your plot list seems to have a missing item. Here's a minimal example
library(ggplot2)
pl <- replicate(13, ggplot(), simplify = FALSE)
ggsave("mp.pdf", gridExtra::marrangeGrob(grobs = pl, nrow=3, ncol=2))
Notes:
you were missing dev.off() hence the invalid pdf
do.call is no longer necessary in (m)arrangeGrob, use the grobs argument
Here's a solution with gridExtra and tidyr
(i) transform the wide data to long-format, and split into a list of data.frame based on each name:
library(tidyr)
df <- d %>% gather(var, val, -time)
df_list <- split(df, df$var)
(ii) plot for each name with lapply function
plots <- lapply(names(df_list), function(x){
ggplot(df_list[[x]], aes(time, val)) +
geom_point() +
labs(x="time", title=x)
})
(iii) using gridExtra to print 12 plots each on two pages of the pdf:
library(gridExtra)
pdf("something.pdf")
do.call(grid.arrange, c(plots[1:12], nrow=4))
do.call(grid.arrange, c(plots[13:24], nrow=4))
dev.off()

Put row and column titles using grid.arrange in R

The data for the ggplots:
set.seed(0)
library(ggplot2)
library(gridExtra)
c <- list()
for (k in 1:9) c[[k]] <- ggplot(data.frame(x=1:10,y=rnorm(10)),aes(x=x,y=y))+geom_line()
grid.arrange (c[[1]],c[[2]],c[[3]],c[[4]],c[[5]]
,c[[6]],c[[7]],c[[8]],c[[9]],ncol=3, nrow=3, widths = c(4,4,4) ,heights = c(4,4,4))
I want titles for each row and each column.
The shape of the output would be something like this:
CTitle 1 CTitle 2 CTitle 3
RTitle1 plot1 plot2 plot3
RTitle2 plot4 plot5 plot6
RTitle3 plot7 plot8 plot9
You can use nested arrangeGrob calls for each column/row, setting the top and left argument. Something like this:
grid.arrange (arrangeGrob(c[[1]], top="CTitle1", left="RTitle1"),arrangeGrob(c[[2]],top="CTitle2"),arrangeGro‌​b(c[[3]],top="CTittl‌​e3"),arrangeGrob(c[[‌​4]], left="RTitle2"),c[[5]],c[[6]],arrangeGrob(c[[7]],left="RTitl‌​e3"),c[[8]],c[[9]],n‌​col=3, nrow=3, widths = c(4,4,4) ,heights = c(4,4,4))
Below is a code to streamline the process thanks to #eipi10
# Create list of plots
set.seed(0)
pl = lapply(1:9, function(i) {
p = ggplot(data.frame(x=1:10,y=rnorm(10)),aes(x, y)) +
geom_line()
})
# Create row and column titles
col.titles = paste("C_Title", 1:3)
row.titles = paste("R_Title", 4:6)
# Add row titles
pl[1:3] = lapply(1:3, function(i) arrangeGrob(pl[[i]], left=row.titles[i]))
# Add column titles and lay out plots
grid.arrange(grobs=lapply(c(1,4,7), function(i) {
arrangeGrob(grobs=pl[i:(i+2)], top=col.titles[i/3 + 1], ncol=1)
}), ncol=3)
here's another option:
pl <- replicate(12, ggplot(), FALSE)
N <- length(pl)
nr <- 4
nc <- 3
combine <- rbind(tableGrob(t(c(letters[1:nc])), theme = ttheme_minimal(), rows = ""),
cbind(tableGrob(LETTERS[1:nr], theme = ttheme_minimal()),
arrangeGrob(grobs = pl), size = "last"), size = "last")
grid.newpage()
grid.draw(combine)

Resources