Related
I am enjoying the patchwork package quite a bit and I am generally happy with even its default formatting.
However, I cannot figure out how to get a reasonable result when trying to display many plots. The output is unreadable (plots shrunk down and dominated by text) and the saved output is completely blank.
Input:
require(ggplot2)
require(patchwork)
plots <- list()
testfunction <- function(x) {
plot_placeholder <- ggplot(mtcars) +
geom_point(aes(mpg, disp)) +
ggtitle(paste("p", x, sep = ""))
plots[[length(plots) + 1]] <<- plot_placeholder
}
mapply(testfunction, c(1:66), SIMPLIFY = FALSE)
patchwork::wrap_plots(plots)
ggsave("test.pdf")
Output:
Is there a way within patchwork to make the page larger or wrap plots across multiple pages of a PDF? Or is there a different package that may help with this?
Update:
Maurits Evers pointed out that this is an issue with my arguments in ggsave(), not patchwork. With these changes the plots look much better in the .pdf output, but were still being truncated at the bottom of page 1. From this post, found the last bit of change needed to generate desired results
Input:
# ...
pdf()
patchwork::wrap_plots(plots)
ggsave("test.pdf", width = 20, height = 20)
dev.off()
Output:
Is there a way to force an automatic line break in the ggtitle command?
As part of a shiny application I use different plots with an input variable for the title.
Unfortunately, some of these variable values are too long to be displayed.
I came across one possibility by inserting \n (or a line break) manually in advance (Details here: Improve editing of multiline title in ggplot that uses \n and extends far to the right). There, something like ggtitle(paste("", title, "", sep = "\n")) would be suggested.
Since including \n would be error prone as well as not flexible for different plot sizes I´m looking for another possibility.
Here is an minimal working example (adapted from lawyeR question linked above):
DF <- data.frame(x = rnorm(400))
title_example <- "This is a very long title describing the plot in its details. The title should be fitted to a graph, which is itself not restricted by its size."
plot <- ggplot(DF, aes(x = x)) + geom_histogram() +
ggtitle(title_example)
You can find a image here: https://i.stack.imgur.com/6MMKF.jpg
Do you have an idea how to e.g. adapt the sep = operator to break lines automatically or are there maybe packages/ workarounds? Thanks!
The ggtext package's text elements could help solve this. element_textbox_simple() automatically wraps the text inside. Try resizing the graphics device window, it adapts!
library(ggplot2)
library(ggtext)
DF <- data.frame(x = rnorm(400))
title_example <- "This is a very long title describing the plot in its details. The title should be fitted to a graph, which is itself not restricted by its size."
ggplot(DF, aes(x = x)) + geom_histogram() +
ggtitle(title_example) +
theme(plot.title = element_textbox_simple())
#> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
I tried to use the plotly package, but it is not working in my case at all. The ggplot package is working for 2D plots but it is giving an error when adding one more axis. How to solve this issue?
ggplot(data,aes(x=D1,y=D2,z=D3,color=Sample)) +
geom_point()
How to add one more axis and get the 3D plot in this?
Since you tagged your question with plotly and said that you've tried to use it with plotly, I think it would be helpful to give you a working code solution in plotly:
Creating some data to plot with:
set.seed(417)
library(plotly)
temp <- rnorm(100, mean=30, sd=5)
pressure <- rnorm(100)
dtime <- 1:100
Graphing your 3d scatterplot using plotly's scatter3d type:
plot_ly(x=temp, y=pressure, z=dtime, type="scatter3d", mode="markers", color=temp)
Renders the following:
ggplot as others have note, by itself does not support 3d graphics rendering.
A possible solutions is gg3D.
gg3D is a package created to extend ggplot2 to produce 3D plots. It does exactly what you are asking for: it adds a third axis to a ggplot. I find it quite good and easy to use and that is what I use for my limited needs.
An example taken from the vignette to produce a basic plot
devtools::install_github("AckerDWM/gg3D")
library("gg3D")
## An empty plot with 3 axes
qplot(x=0, y=0, z=0, geom="blank") +
theme_void() +
axes_3D()
## Axes can be populated with points using the function stat_3D.
data(iris)
ggplot(iris, aes(x=Petal.Width, y=Sepal.Width, z=Petal.Length, color=Species)) +
theme_void() +
axes_3D() +
stat_3D()
There are other options not involving ggplot. For example the excellent plot3D package with its extension plot3Drgl to plot in openGL.
In your question, you refer to the plotly package and to the ggplot2 package. Both plotly and ggplot2 are great packages: plotly is good at creating dynamic plots that users can interact with, while ggplot2 is good at creating static plots for extreme customization and scientific publication. It is also possible to send ggplot2 output to plotly. Unfortunately, at the time of writing (April 2021), ggplot2 does not natively support 3d plots. However, there are other packages that can be used to produce 3d plots and some ways to get pretty close to ggplot2 quality. Below I review several options. These suggestions are by no means exhaustive.
plotly
See onlyphantom's answer in this thread.
gg3D
See Marco Stamazza's answer in this thread. See also my effort below.
scatterplot3d
See Seth's answer in a related thread.
lattice
See Backlin's answer in a related thread.
rgl
See this overview in the wiki guide.
rayshader
See this overview of this package's wonderful capabilities.
trans3d
See data-imaginist use trans3d to get a cube into ggplot2.
ggrgl
See this cool and useful coolbutuseless introduction.
Now let me review some of my efforts with the Lorenz attractor trajectories. While customization remains limited, I've had best results for PDF output with gg3D. I also include a ggrgl example.
gg3D
# Packages
library(deSolve)
library(ggplot2)
library(gg3D) # remotes::install_github("AckerDWM/gg3D")
# Directory
setwd("~/R/workspace/")
# Parameters
parms <- c(a=10, b=8/3, c=28)
# Initial state
state <- c(x=0.01, y=0.0, z=0.0)
# Time span
times <- seq(0, 50, by=1/200)
# Lorenz system
lorenz <- function(times, state, parms) {
with(as.list(c(state, parms)), {
dxdt <- a*(y-x)
dydt <- x*(c-z)-y
dzdt <- x*y-b*z
return(list(c(dxdt, dydt, dzdt)))
})
}
# Make dataframe
df <- as.data.frame(ode(func=lorenz, y=state, parms=parms, times=times))
# Make plot
make_plot <- function(theta=0, phi=0){
ggplot(df, aes(x=x, y=y, z=z, colour=time)) +
axes_3D(theta=theta, phi=phi) +
stat_3D(theta=theta, phi=phi, geom="path") +
labs_3D(theta=theta, phi=phi,
labs=c("x", "y", "z"),
angle=c(0,0,0),
hjust=c(0,2,2),
vjust=c(2,2,-2)) +
ggtitle("Lorenz butterfly") +
theme_void() +
theme(legend.position = "none")
}
make_plot()
make_plot(theta=180,phi=0)
# Save plot as PDF
ggsave(last_plot(), filename="lorenz-gg3d.pdf")
Pros: Outputs high-quality PDF:
Cons: Still limited customization. But for my specific needs, currently the best option.
ggrgl
# Packages
library(deSolve)
library(ggplot2)
library(rgl)
#remotes::install_github("dmurdoch/rgl")
library(ggrgl)
# remotes::install_github('coolbutuseless/ggrgl', ref='main')
library(devout)
library(devoutrgl)
# remotes::install_github('coolbutuseless/devoutrgl', ref='main')
library(webshot2)
# remotes::install_github("rstudio/webshot2")
library(ggthemes)
# Directory
setwd("~/R/workspace/")
# Parameters
parms <- c(a=10, b=8/3, c=26.48)
# Initial state
state <- c(x=0.01, y=0.0, z=0.0)
# Time span
times <- seq(0, 100, by=1/500)
# Lorenz system
lorenz <- function(times, state, parms) {
with(as.list(c(state, parms)), {
dxdt <- a*(y-x)
dydt <- x*(c-z)-y
dzdt <- x*y-b*z
return(list(c(dxdt, dydt, dzdt)))
})
}
# Make dataframe
df <- as.data.frame(ode(func=lorenz, y=state, parms=parms, times=times))
# Make plot
ggplot(df, aes(x=x, y=y, z=z)) +
geom_path_3d() +
ggtitle("Lorenz butterfly") -> p
# Render Plot in window
rgldev(fov=30, view_angle=-10, zoom=0.7)
p + theme_ggrgl(16)
# Save plot as PNG
rgldev(fov=30, view_angle=-10, zoom=0.7,
file = "~/R/Work/plots/lorenz-attractor/ggrgl/lorenz-ggrgl.png",
close_window = TRUE, dpi = 300)
p + theme_ggrgl(16)
dev.off()
Pros: The plot can be rotated in a way similar to plotly. It is possible to 'theme' a basic plot:
Cons: The figure is missing a third axis with labels. Cannot output high-quality plots. While I've been able to view and save a low-quality black trajectory in PNG, I could view a colored trajectory like the above, but could not save it, except with a low-quality screenshot:
Related threads: plot-3d-data-in-r, ploting-3d-graphics-with-r.
Is it (reasonably) possible to plot a sequence logo plot using ggplot2?
There is a package to do it which is based on "grid" called "seqLogo", but I was wondering if there could be a ggplot2 version of it.
Thanks.
ggseqlogo should be what you're looking for. I hope this can relieve some of the frustrations I’m sure many of you have when it comes to plotting sequence logos in R
I'm submitting a ggplot2 attempt that is somewhat similar to the Leipzig/Berry solution above. This format is a little bit closer to the standard logogram.
But my solution, and I think any ggplot2 solution, still falls short because ggplot2 does not offer control over the aspect ratio of plotting symbols. This is the core capability that (I think) is required for generating sequence logos and that is missing from ggplot2.
Also note: I used the data from Jeremy Leipzig's answer, but I did not do any corrections for small sample sizes or for %GC values different than 50%.
require(ggplot2)
require(reshape2)
freqs<-matrix(data=c(0.25,0.65,0.87,0.92,0.16,0.16,0.04,0.98,0.98,1.00,0.02,0.10,0.10,0.80,0.98,0.91,0.07,0.07,0.11,0.05,0.04,0.00,0.26,0.17,0.00,0.01,0.00,0.00,0.29,0.17,0.01,0.03,0.00,0.00,0.32,0.32,0.53,0.26,0.07,0.02,0.53,0.18,0.96,0.01,0.00,0.00,0.65,0.01,0.89,0.17,0.01,0.09,0.59,0.12,0.11,0.04,0.02,0.06,0.05,0.49,0.00,0.00,0.02,0.00,0.04,0.72,0.00,0.00,0.01,0.00,0.02,0.49),byrow=TRUE,nrow=4,dimnames=list(c('A','C','G','T')))
freqdf <- as.data.frame(t(freqs))
freqdf$pos = as.numeric(as.character(rownames(freqdf)))
freqdf$height <- apply(freqdf[,c('A', 'C','G','T')], MARGIN=1,
FUN=function(x){2-sum(log(x^x,base=2))})
logodf <- data.frame(A=freqdf$A*freqdf$height, C=freqdf$C*freqdf$height,
G=freqdf$G*freqdf$height, T=freqdf$T*freqdf$height,
pos=freqdf$pos)
lmf <- melt(logodf, id.var='pos')
quartz(height=3, width=8)
ggplot(data=lmf, aes(x=as.numeric(as.character(pos)), y=value)) +
geom_bar(aes(fill=variable,order=value), position='stack',
stat='identity', alpha=0.5) +
geom_text(aes(label=variable, size=value, order=value, vjust=value),
position='stack') +
theme_bw()
quartz.save('StackOverflow_5438474.png', type='png')
That produces this graph:
I have implemented an alternative designed by Charles Berry, which addresses some of the weaknesses of seqLogos discussed ad nauseam in the comment section below. It uses ggplot2:
library("devtools")
install_github("leipzig/berrylogo")
library("berrylogo")
freqs<-matrix(data=c(0.25,0.65,0.87,0.92,0.16,0.16,0.04,0.98,0.98,1.00,0.02,0.10,0.10,0.80,0.98,0.91,0.07,0.07,0.11,0.05,0.04,0.00,0.26,0.17,0.00,0.01,0.00,0.00,0.29,0.17,0.01,0.03,0.00,0.00,0.32,0.32,0.53,0.26,0.07,0.02,0.53,0.18,0.96,0.01,0.00,0.00,0.65,0.01,0.89,0.17,0.01,0.09,0.59,0.12,0.11,0.04,0.02,0.06,0.05,0.49,0.00,0.00,0.02,0.00,0.04,0.72,0.00,0.00,0.01,0.00,0.02,0.49),byrow=TRUE,nrow=4,dimnames=list(c('A','C','G','T')))
p<-berrylogo(freqs,gc_content=.41)
print(p)
No direct way to do so in ggplot2, as far as I'm concerned.
However, check out RWebLogo. It's an R wrapper I have written for the WebLogo python library. You can download it from CRAN and it's hosted on github
Simple example:
# Load package
library('RWebLogo')
# Sample alignment
aln <- c('CCAACCCAA', 'CCAACCCTA', 'AAAGCCTGA', 'TGAACCGGA')
# Plot logo to file
weblogo(seqs=aln, file.out='logo.pdf')
# Plot logo to R graphics device (uses generated jpeg logo and raster package)
weblogo(seqs=aln, plot=TRUE, open=FALSE, format='jpeg', resolution=600)
For more options see ?weblogo or ?plotlogo
Here is an alternative option. motiflogo is a new representation of motif (sequence) logo implemented by ggplot2. Two aspects could be considered.
As a canonical motif logo representation
As a SNP-specific motif logo representation
There is now a gglogo package (also on CRAN, yet another amazing ggplot2 extension by Heike Hofmann).
This package that produces plots like these:
library(ggplot2)
library(gglogo)
ggplot(data = ggfortify(sequences, "peptide")) +
geom_logo(aes(x=position, y=bits, group=element,
label=element, fill=interaction(Polarity, Water)),
alpha = 0.6) +
scale_fill_brewer(palette="Paired") +
theme(legend.position = "bottom")
The example is from https://github.com/heike/gglogo/blob/master/visual_test/logos.R and there's a manuscript on the package here: https://github.com/heike/logopaper/blob/master/logos.Rmd
Is it (reasonably) possible to plot a sequence logo plot using ggplot2?
There is a package to do it which is based on "grid" called "seqLogo", but I was wondering if there could be a ggplot2 version of it.
Thanks.
ggseqlogo should be what you're looking for. I hope this can relieve some of the frustrations I’m sure many of you have when it comes to plotting sequence logos in R
I'm submitting a ggplot2 attempt that is somewhat similar to the Leipzig/Berry solution above. This format is a little bit closer to the standard logogram.
But my solution, and I think any ggplot2 solution, still falls short because ggplot2 does not offer control over the aspect ratio of plotting symbols. This is the core capability that (I think) is required for generating sequence logos and that is missing from ggplot2.
Also note: I used the data from Jeremy Leipzig's answer, but I did not do any corrections for small sample sizes or for %GC values different than 50%.
require(ggplot2)
require(reshape2)
freqs<-matrix(data=c(0.25,0.65,0.87,0.92,0.16,0.16,0.04,0.98,0.98,1.00,0.02,0.10,0.10,0.80,0.98,0.91,0.07,0.07,0.11,0.05,0.04,0.00,0.26,0.17,0.00,0.01,0.00,0.00,0.29,0.17,0.01,0.03,0.00,0.00,0.32,0.32,0.53,0.26,0.07,0.02,0.53,0.18,0.96,0.01,0.00,0.00,0.65,0.01,0.89,0.17,0.01,0.09,0.59,0.12,0.11,0.04,0.02,0.06,0.05,0.49,0.00,0.00,0.02,0.00,0.04,0.72,0.00,0.00,0.01,0.00,0.02,0.49),byrow=TRUE,nrow=4,dimnames=list(c('A','C','G','T')))
freqdf <- as.data.frame(t(freqs))
freqdf$pos = as.numeric(as.character(rownames(freqdf)))
freqdf$height <- apply(freqdf[,c('A', 'C','G','T')], MARGIN=1,
FUN=function(x){2-sum(log(x^x,base=2))})
logodf <- data.frame(A=freqdf$A*freqdf$height, C=freqdf$C*freqdf$height,
G=freqdf$G*freqdf$height, T=freqdf$T*freqdf$height,
pos=freqdf$pos)
lmf <- melt(logodf, id.var='pos')
quartz(height=3, width=8)
ggplot(data=lmf, aes(x=as.numeric(as.character(pos)), y=value)) +
geom_bar(aes(fill=variable,order=value), position='stack',
stat='identity', alpha=0.5) +
geom_text(aes(label=variable, size=value, order=value, vjust=value),
position='stack') +
theme_bw()
quartz.save('StackOverflow_5438474.png', type='png')
That produces this graph:
I have implemented an alternative designed by Charles Berry, which addresses some of the weaknesses of seqLogos discussed ad nauseam in the comment section below. It uses ggplot2:
library("devtools")
install_github("leipzig/berrylogo")
library("berrylogo")
freqs<-matrix(data=c(0.25,0.65,0.87,0.92,0.16,0.16,0.04,0.98,0.98,1.00,0.02,0.10,0.10,0.80,0.98,0.91,0.07,0.07,0.11,0.05,0.04,0.00,0.26,0.17,0.00,0.01,0.00,0.00,0.29,0.17,0.01,0.03,0.00,0.00,0.32,0.32,0.53,0.26,0.07,0.02,0.53,0.18,0.96,0.01,0.00,0.00,0.65,0.01,0.89,0.17,0.01,0.09,0.59,0.12,0.11,0.04,0.02,0.06,0.05,0.49,0.00,0.00,0.02,0.00,0.04,0.72,0.00,0.00,0.01,0.00,0.02,0.49),byrow=TRUE,nrow=4,dimnames=list(c('A','C','G','T')))
p<-berrylogo(freqs,gc_content=.41)
print(p)
No direct way to do so in ggplot2, as far as I'm concerned.
However, check out RWebLogo. It's an R wrapper I have written for the WebLogo python library. You can download it from CRAN and it's hosted on github
Simple example:
# Load package
library('RWebLogo')
# Sample alignment
aln <- c('CCAACCCAA', 'CCAACCCTA', 'AAAGCCTGA', 'TGAACCGGA')
# Plot logo to file
weblogo(seqs=aln, file.out='logo.pdf')
# Plot logo to R graphics device (uses generated jpeg logo and raster package)
weblogo(seqs=aln, plot=TRUE, open=FALSE, format='jpeg', resolution=600)
For more options see ?weblogo or ?plotlogo
Here is an alternative option. motiflogo is a new representation of motif (sequence) logo implemented by ggplot2. Two aspects could be considered.
As a canonical motif logo representation
As a SNP-specific motif logo representation
There is now a gglogo package (also on CRAN, yet another amazing ggplot2 extension by Heike Hofmann).
This package that produces plots like these:
library(ggplot2)
library(gglogo)
ggplot(data = ggfortify(sequences, "peptide")) +
geom_logo(aes(x=position, y=bits, group=element,
label=element, fill=interaction(Polarity, Water)),
alpha = 0.6) +
scale_fill_brewer(palette="Paired") +
theme(legend.position = "bottom")
The example is from https://github.com/heike/gglogo/blob/master/visual_test/logos.R and there's a manuscript on the package here: https://github.com/heike/logopaper/blob/master/logos.Rmd