I want to somehow indicate that certain rows in a multipanel figure should be compared together. For example, I want to make this plot:
Look like this plot (with boxes around panels made with PowerPoint):
Here's the code I made to use the first plot. I used ggplot and cowplot:
require(cowplot)
theme_set(theme_cowplot(font_size=12)) # reduce default font size
plot.mpg <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot.mpg2 <- ggplot(mpg, aes(x = cty, y = hwy, colour = factor(cyl))) +
geom_point(size=2.5)
plot.diamonds2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle=70, vjust=0.5))
plot_grid(plot.mpg, plot.diamonds,plot.mpg2, plot.diamonds2, nrow=2,labels = c('A', 'B','C','D'))
Is there a change I can make to this code to get the borders that I want? Or maybe can I even make the panels A and B have a slightly different color than the background for panels C and D? That might be even better.
Since the result of plot_grid() is a ggplot object, one way to do this is to use nested plot grids: one plot_grid() for each row, with the appropriate border added via theme().
plot_grid(
# row 1
plot_grid(plot.mpg, plot.diamonds, nrow = 1, labels = c('A', 'B')) +
theme(plot.background = element_rect(color = "black")),
# row 2
plot_grid(plot.mpg2, plot.diamonds2, nrow = 1, labels = c('C', 'D')) +
theme(plot.background = element_rect(color = "black")),
nrow = 2)
Related
I'm struggling with a problem:
I created two volcano plots in ggplot2, but due to the fact that I had one outlier point in both plot, I need to add y axis break for better visualization.
The problem arises when I WANT TO plot both in the same page using plot_grid from cowplot::, because it visualizes the original plot without the breaks that I set.
p<- c1 %>%
ggplot(aes(x = avg_log2FC,
y = -log10(p_val_adj),
fill = gene_type,
size = gene_type,
alpha = gene_type)) +
geom_point(shape = 21, # Specify shape and colour as fixed local parameters
colour = "black") +
geom_hline(yintercept = 0,
linetype = "dashed") +
scale_fill_manual(values = cols) +
scale_size_manual(values = sizes) +
scale_alpha_manual(values = alphas) +
scale_x_continuous(limits=c(-1.5,1.5), breaks=seq(-1.5,1.5,0.5)) +
scale_y_continuous(limits=c(0,110),breaks=seq(0,110,25))+
labs(title = "Gene expression",
x = "log2(fold change)",
y = "-log10(adjusted P-value)",
colour = "Expression \nchange") +
theme_bw() + # Select theme with a white background
theme(panel.border = element_rect(colour = "black", fill = NA, size= 0.5),
panel.grid.minor = element_blank(),
panel.grid.major = element_blank())
p1 <- p + scale_y_break(breaks = c(30, 100))
p1
p plot without breaks:
and p1 plot with breaks:
The same I did for the second plot. But this is the result using plot_grid(p1,p3, ncol = 2)
Can you help me understanding if I'm doing something wrong? or it is just a limitation of the package?
OP, it seems in that ggbreak is not compatible with functions that arrange multiple plots, as indicated in the documentation for the package here. There does seem to be a workaround via either print() (I didn't get this to work) or aplot::plot_list(...), which did work for me. Here's an example using built-in datasets.
# setting up the plots
library(ggplot2)
library(ggbreak)
library(cowplot)
p1 <-
ggplot(mtcars, aes(x=mpg, disp)) + geom_point() +
scale_y_break(c(200, 220))
p2 <-
ggplot(iris, aes(x=Sepal.Length, y=Sepal.Width, color=Species)) +
geom_point() + scale_y_break(c(3.5, 3.7))
Plots p1 and p2 yield breaks in the y axis like you would expect, but plot_grid(p1,p2) results in the plots placed side-by-side without the y axis breaks.
The following does work to arrange the plots without disturbing the y axis breaks:
aplot::plot_list(p1,p2)
I am trying to plot a scatter plot with 22 variables, so they all need to have different markers. I thought of repeating some shapes and colors from RColorBrew, and everything works fine, except for the legend that does not update with the colors I selected (please see image below). I also attached a working example below. What could I possibly be doing wrong?
#!/usr/bin/env Rscript
library(ggplot2)
library(ggpubr)
library(RColorBrewer)
theme_set(
theme_pubr()
)
data <- data.frame(
x = c(1:22),
y = as.factor(c(1:22))
)
shapes <- rep(15:18, 6)
colors <- rep(brewer.pal(n = 11, name = "Paired"), 2)
plot <- ggplot(data, aes(x=x, y=y, group=y, size=9, color=colors)) +
geom_point(aes(shape=y)) +
scale_shape_manual(values=shapes) +
scale_size(guide="none") +
guides(fill="none", color="none")
plot <- plot + theme(panel.grid.major=element_line(colour="gray", size=0.2),
panel.grid.minor=element_line(colour="gray", size=0.2))
print(plot)
There are two issues:
I you want to have your colors make use of scale_color_manual and map y on the color aes as you did with shape
The reason your legend does not get colored is that you have set guides(color = "none")
library(ggplot2)
library(ggpubr)
library(RColorBrewer)
theme_set(
theme_pubr()
)
data <- data.frame(
x = c(1:22),
y = as.factor(c(1:22))
)
shapes <- rep(15:18, 6)
colors <- rep(brewer.pal(n = 11, name = "Paired"), 2)
plot <- ggplot(data, aes(x = x, y = y, group = y, size = 9)) +
geom_point(aes(shape = y, color = y)) +
scale_shape_manual(values = shapes) +
scale_color_manual(values = colors) +
scale_size(guide = "none") +
guides(fill = "none")
plot + theme(
panel.grid.major = element_line(colour = "gray", size = 0.2),
panel.grid.minor = element_line(colour = "gray", size = 0.2)
)
I found a number of things going on. I broke them down one by one here:
You're including colors in the aes but it's not a part of the data, it's just the color palette, so that shouldn't be included here. aes is telling ggplot what data to show, not how to format it.
geom_point needs both a color and shape aes argument so that it can combine them and later tell the legend how it has done so.
To control the color palette used, I added scale_color_manual, similar to how you were already using scale_shape_manual to manually adjust formatting
Remove the guides line at the end. by setting color = "none" it's blocking color from being added to the legend.
Try the segment of code below.
data <- data.frame(
x = c(1:22),
y = as.factor(c(1:22))
)
shapes <- rep(15:18, 6)
colors <- rep(brewer.pal(n = 11, name = "Paired"), 2)
#OLD: plot <- ggplot(data, aes(x=x, y=y, group=y, size=9, color=colors)) +
plot <- ggplot(data, aes(x=x, y=y, group=y, size=9)) +
#OLD: geom_point(aes(shape=y)) +
geom_point(aes(shape=y, color=y)) +
scale_shape_manual(values=shapes) +
#NEW LINE
scale_color_manual(values = colors) +
scale_size(guide="none")
# REMOVED guides(fill="none", color="none")
plot <- plot + theme(panel.grid.major=element_line(colour="gray", size=0.2),
panel.grid.minor=element_line(colour="gray", size=0.2))
print(plot)
Below is my code to plot Stacked BarPlot
ggplot(data = mdata, aes(x = variable, y = value, fill = Species)) +
geom_bar(position = "fill", stat = "identity") +
theme(legend.text=element_text(size=rel(0.7)),
legend.key.size = unit(0.5, "cm")) +
scale_y_continuous(labels=function(x)x*100) +
coord_flip() +
ylab("Species Percentage") +
xlab("Samples")
OutputPlot:
As you can see from the plot my Species legends are split in to 5 column list, which takes the 50% of the total plot layout.
Is there a way to make/convert legend list in to only 2 or 3 column so that area above and below will be covered and BarPlot can be widened.
Also to make Legend Text Bold its looking blurred with many legends
You can set any number of columns with the ncol argument in guide_legend():
library(ggplot2)
dat <- cbind(car = rownames(mtcars), mtcars)
ggplot(dat, aes(mpg, wt, colour = car)) +
geom_point() +
scale_colour_discrete(guide = guide_legend(ncol = 3))
EDIT: As Z.Lin pointed out, for fill scales; replace scale_colour_* by scale_fill_*.
I'd like to add a line below the x-axis where its color is dependant on a factor that is not plotted.
In this example, I'm creating a box plot and would like to add a line that indicates another variable.
Using the cars data set as an example and then physically dawing in what I'm trying to do:
ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot()
My thought was to create a bar, column, or geom_tile plot and then arrange it below the boxplot. This is how I would do it in base R. Is there a way to add in these kinds of color labels in ggplot2?
The natural way in ggplot2 to do this sort of thing would to be facet on the categorical variable to create subplots. However if you want to keep everything on the same graph you could try using a geom_tile() layer something like this:
df <-data.frame(x = factor(c(4,6,8)), colour = factor(c(1,2,1)))
ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot() +
geom_tile(data=df, aes(x = x, y = 8, fill = colour))
Alternatively as you suggest you could align an additional plot underneath it. You could use ggarrange() in the ggpubr package for this:
plot1 <- ggplot(mtcars, aes(factor(cyl), mpg, fill=factor(am))) +
geom_boxplot() +
geom_tile(data=df, aes(x = x, y = 10, fill = colour))
theme(legend.position = 'none')
plot2 <- ggplot(df, aes(x=x, y=1, fill = colour)) +
geom_tile() +
theme_void() +
scale_fill_manual(values=c('orange', 'green', 'orange')) +
theme(legend.position = 'none')
library(ggpubr)
ggarrange(plot1, plot2, nrow = 2, heights = c(10, 1), align = 'h')
I am making a presentation and would like to present one line graph (geom_line()) with an appropriate legend. I then want to overlay a new geom_line and add the corresponding legend item. For aesthetic reasons, I want the overlay to not modify the legend location given in the first plot. The effect should be that one is drawing on an existing graph, and adding to its legend.
If I simply using ggplot to first make the first plot and then make a new plot with both lines, the location of the legend changes noticeably.
If I try to make the first plot be the full plot, but setting one of the line sizes to zero, I run into the problem that I can't suppress the legend-item for the size-zero line.
How can I achieve my desired effect with ggplot2?
EDIT:
Here is the code to make the two graphs that I first naively tried.
require(ggplot2)
require(reshape2)
x<-seq(-10,10,length=200)
G <- (1/(sqrt(2*pi))) * exp(-((x)^2)/(2))
G2 <- 2*(1/(pi))*(1/(x^2+1))
df = data.frame(x,G,G2)
ggplot(data = melt(data.frame(x,G),id.vars = 'x'))+
geom_line(aes(x=x, y=value, color=variable),size=.5)+
scale_color_manual("Distribution",values=c("orange"),labels=c("Gaussian"))+
coord_cartesian(ylim = c(0, 1))
ggplot(data = melt(data.frame(x,G,G2),id.vars = 'x'))+
geom_line(aes(x=x, y=value, color=variable),size=.5)+
scale_color_manual("Distribution",values=c("orange","blue"),labels=c("Gaussian","2Gaussian"))+
coord_cartesian(ylim = c(0, 1))
If it's not clear from these pictures that there is a problem, open up the images from these two links and flip from one to another.
http://rpubs.com/jwg/269311
http://rpubs.com/jwg/269312
NOTICE: The problem is even worse than I first described, since not only is the legend moving but the coordinate axis is moving as well.
Presumably this can be fixed by plotting both and then making its legend-item and the line invisible. Is this a possibility?
Here's a solution which will keep everything aligned with the bonus of animation.
library(ggplot2)
library(tidyr)
library(gganimate)
p <- df %>%
gather(var, val, -x) %>%
ggplot(aes(x, val, frame = var)) +
geom_line(aes(color = var, group = var, cumulative = TRUE)) +
coord_cartesian(ylim = c(0, 1))
gganimate(p, "myplot.gif", "gif")
This should generate a file myplot.gif with this result:
Not sure if this is what you want, but here goes:
x<-seq(-10,10,length=200)
G <- (1/(sqrt(2*pi))) * exp(-((x)^2)/(2))
G2 <- 2*(1/(pi))*(1/(x^2+1))
df <- data.frame(x,G,G2)
df.plot <- tidyr::gather(df, key = 'variable', value = 'value', -x)
ggplot(df.plot, aes(x, value, color = variable)) + geom_line() + scale_color_manual(breaks = c("G"), values = c("orange", NA)) +
coord_cartesian(xlim = c(-10, 10), ylim = c(0,1)) + theme(legend.position = c(0,0)) +
theme(legend.position = "right",
legend.justification = "top")
ggplot(df.plot, aes(x, value, color = variable)) + geom_line() + scale_color_manual(breaks = c("G", "G2"), values = c("orange", "blue")) +
coord_cartesian(xlim = c(-10, 10), ylim = c(0,1)) + theme(legend.position = "right",
legend.justification = "top")