Related
guides = "collect" does its job but it locates the legend in a way that it overlaps the plot. I would like it to be placed right in the middle of the empty bottom right corner, but it appears to be difficult since theme(legend.position = c(X,Y)) does not work with patchwork
Illustration of the issue:
This is the code I have for assembling 4 graphs I have using patchwork. Pretty sure there is a more elegant way to use theme() but I am quite new to patchwork and it worked for me so far, except for the legend positioning.
A similar issue was resolved here but it does not seem to help in my case.
#first panel
s_wpanels_final <- (dots & theme_bw() & theme(axis.title.x =
element_blank(), panel.grid.minor.y = element_blank())) +
#second panel
(g_box_tmax & theme_bw() & theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank(), panel.grid.minor.y = element_blank(),
axis.text.y=element_blank(), axis.ticks.y=element_blank(),
axis.title.x = element_blank(), legend.position = "none")) +
#third panel
(g_box_t0 & theme_bw() & theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank(), panel.grid.minor.y = element_blank(),
axis.text.y=element_blank(), axis.ticks.y=element_blank(),
axis.title.x = element_blank(), legend.position = "none")) +
#fourth panel
(tmax_box & theme_bw() & theme(axis.text.x=element_blank(),
axis.ticks.x=element_blank(), axis.text.y=element_blank(),
axis.ticks.y=element_blank(), axis.title.y = element_blank(),
legend.position = "none")) +
guide_area()+
plot_layout(ncol=3, guides = "collect", widths=c(6,1,1), heights=c(6,1)) &
theme(legend.direction = "vertical", legend.box = "horizontal")
There are two issues with your code. First using + to glue your plots together and setting ncol=3 will place the guide_area in the second column of the second row. To center the legend I would suggest to use the design argument to specify the layout of the plot. Second, while the plot panels will adjust to the space set via the height and width arguments and the size of your plotting device, the legend will not, i.e. if the legend will not fit into the space given it will overlap with the surrounding panels. To fix that I would suggest to increase the widths of the second and third columns and the height of the second row. But as I said this also depends on the size of the plotting device.
Using some fake example plot based on mtcars(see below) let's first reproduce your issue:
library(ggplot2)
library(patchwork)
list(
dots,
g_box_tmax,
g_box_t0,
tmax_box,
guide_area()
) |>
wrap_plots() +
plot_layout(guides = "collect", widths = c(6, 1, 1), heights = c(6, 1), ncol = 3) &
theme(legend.direction = "vertical", legend.box = "horizontal")
However, specifying the layout via the design argument and increasing the height of the second row as well as the widths of the second and third columns works fine and centers the legend in the guide area:
design <-
"
ABC
DEE
"
list(
dots,
g_box_tmax,
g_box_t0,
tmax_box,
guide_area()
) |>
wrap_plots() +
plot_layout(guides = "collect", widths = c(6, 1.5, 1.5), heights = c(6, 1.5), design = design) &
theme(legend.direction = "vertical", legend.box = "horizontal")
PLOTS
dots <- ggplot(mtcars, aes(mpg, hp, color = factor(cyl), size = qsec)) +
geom_point() +
theme_bw() +
theme(
axis.title.x = element_blank(),
panel.grid.minor.y = element_blank()
)
g_box_tmax <- g_box_t0 <- ggplot(mtcars, aes(factor(cyl), hp, fill = factor(cyl))) +
geom_boxplot() +
theme_bw() +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(), panel.grid.minor.y = element_blank(),
axis.text.y = element_blank(), axis.ticks.y = element_blank(),
axis.title.x = element_blank(), legend.position = "none"
)
tmax_box <- ggplot(mtcars, aes(mpg, factor(cyl), fill = factor(cyl))) +
geom_boxplot() +
theme_bw() +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(), axis.text.y = element_blank(),
axis.ticks.y = element_blank(), axis.title.y = element_blank(),
legend.position = "none"
)
What causes the legend box (which is too big for the plot dimension) to be positioned there, is probably some quite clever patchwork code, and is related to guide_area (therefore my question title edit).
The below is a slightly unsatisfactory, but effective hack to modify the position. It's a bit of a trial and error. Simply give a negative margin to the legend box to the right and it will "drag" the box accordingly.
I've removed all the legend.position = "none" from your plots as this is not necessary with guides = "collect"
library(ggplot2)
library(patchwork)
p1 <- ggplot(iris) + geom_point(aes(Sepal.Length, Sepal.Width, color = Species, size = Petal.Length))
p2 <- ggplot(iris) + geom_point(aes(Sepal.Length, Sepal.Width, color = Species, size = Petal.Length))
p3 <- ggplot(iris) + geom_point(aes(Sepal.Length, Sepal.Width, color = Species, size = Petal.Length))
p4 <- ggplot(iris) + geom_point(aes(Sepal.Length, Sepal.Width, color = Species, size = Petal.Length))
p1 + p2 + p3 + p4 +
guide_area()+
plot_layout(ncol=3, guides = "collect", widths=c(6,1,1), heights=c(6,1)) &
theme(legend.direction = "vertical", legend.box = "horizontal",
legend.box.margin = margin(r = -1, unit = "in"))
I am trying to make a stacked and grouped barplot using the following datasets:
dfplot <- data.frame(organisms=c("M.musculus","D.melanogaster" ,"H.sapiens","O.sativa","S.pombe","C.familiaris",
"G.gallus","P.falciparum","A.thaliana","C.elegans","D.rerio","B.taurus","S.cerevisiae","R.norvegicus","C.intestinalis","B.subtilis","E.coli"),
KEGGv2=c(20,7,21,126,106,62,26,80,5,5,13,306,8,35,32,104,107),
KEGGv1=c(286,124,289,0,0,244,135,0,121,124,148,0,101,271,87,0,0),
Reactome=c(358,146,596,115,54,306,370,23,155,112,365,341,52,364,0,0,0))
# Melt the dataframe
melted <- melt(dfplot, "organisms")
# Reformat the data labels
melted$cat <- ''
melted[melted$variable == 'Reactome',]$cat <- "Reactome"
melted[melted$variable != 'Reactome',]$cat <- "KEGG"
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~ organisms)+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
strip.text.x = element_blank(),
strip.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"))
And my output is the following one:
I used a facet_grid per organism because I wanted to have a mix between stack (for both KEGGv1 and KEGGv2) and then group it with the other group Reactome. However, when doing the melting, the x-axis will have two labels per facet_grid (KEGG and Reactome, which is the variable obtained from the melting [cat]). I did not want that label so I remove them.
What I am trying to do is to have the organism name per each of the groupings, so each of the 17 grouping bars will have the name of the corresponding organism**. Therefore, I am missing that, I have tried several ways but I cannot find the proper way of doing it.
Thanks in advance,
You can do two things to make this work:
Rotate the labels of the facet so that they plot at 90 degrees
Plot the facet labels beneath the graph using the switch = 'x' argument within facet_grid.
Here is the complete example:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~organisms, switch = 'x')+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.y = element_line(colour = "black"),
strip.text = element_text(angle = 90))
I left the default shaded background, but you can easily style as you prefer.
Aproach Two
You might want to consider rotating the plot. This requires you to flip the coordinates of the plot using coord_flip before the facet is called. As we are faceting in the other direction we change the facet argument to facet_grid(organisms~.). All other arguments which refer to x or y are swapped over:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
coord_flip() +
facet_grid(organisms~., switch = 'y') +
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.x = element_line(colour = "black"),
strip.text.y = element_text(angle = 180))
First you can set the organism labels to be below the bars, rather than above. This is established by setting the switch argument of the facet_grid function to "x" (see code below). Secondly, you should then remove axis.title.x=element_blank() argument within your theme function call. The updated code is below. Hope this helps!
ggplot(melted, aes(x = cat, y = value, fill =variable)) +
geom_bar(stat = 'identity', position = 'stack') +facet_grid(~organisms, switch="x")+
scale_fill_manual(values=c("deepskyblue4","lightblue1","olivedrab2"))+
ylab("Number of pathways")+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank())+theme(legend.title=element_blank())+
theme(strip.background = element_blank())+theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),panel.background = element_blank(), axis.line = element_line(colour = "black"))
I have a plot in ggplot:
ggplot(plot1,aes(x=c,y=value,colour=variable,linetype=variable,size=variable)) +
geom_line() +
scale_x_continuous(breaks=seq(1,10,1)) +
scale_y_continuous(breaks=seq(0,1, 0.1))+
scale_colour_manual(values=rep(c("blue3","red3"),each=9)) +
scale_linetype_manual(values = rep(c(3,1),each=9)) +
scale_size_manual(values = rep(c(0.6,0.3),each=9)) +
theme_bw(base_size=12, base_family="Helvetica") +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=8),
text = element_text(size=14),
axis.line = element_line(size=0.25),
axis.ticks=element_line(size=0.25),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
legend.position="none" ,
legend.direction="vertical",
legend.title=element_blank(),
legend.text=element_text(size=8),
legend.background=element_blank(),
legend.key=element_blank())+labs(title='a',x='b', y='c' )+theme(plot.title=element_text(size=8))+theme(plot.margin=unit(c(0.1,0,0.1,0),"cm"))
I would like to disable:
the numbers on the y axis
the small lines indicating the position of the numbers
the label
Is this possible to do without affecting the x axis?
I think you can use this approach.
p1 + theme(axis.text.y=element_blank())+ylab("") + scale_y_discrete(breaks=NULL)
# p1 = your initial graph
# axis.text.y removes number
# ylab("") removes y label
# scale_y_discrete(breaks=NULL) removes the tick marks. Your x-axis will not be affected.
Good luck.
You can also do everything in the theme() part of your code. Just add the following code:
p1 + theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
I have the following plot:
ggplot(proba[108:140,], aes(c,four, color="a1")) +
geom_line(linetype=1, size=0.3) +
scale_x_continuous(breaks=seq(110,140,5)) +
theme_bw() +
theme(axis.line = element_line(colour = "black", size=0.25),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank()) +
theme(axis.text.x = element_text(angle = 0, hjust = +0.5, size=6,color="black")) +
theme(axis.text.y = element_text(angle = 0, hjust = -100, size=6, color="black")) +
theme(axis.ticks=element_line(colour="black",size=0.25)) +
xlab("\nTime-steps")+ylab("Proportion correct\n") +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=8)) +
geom_line(aes(c,three, color="a2"), size=0.2, linetype=2) +
geom_line(aes(c,one, color="a3"),linetype=3, size=0.8) +
geom_line(aes(c,two, color="a4"), linetype=1, size=0.6) +
scale_color_manual(values=c("a1"="red3", "a2"="red3","a3"="blue3","a4"="blue3")) +
theme(legend.title = element_text(colour="black", size=7)) +
theme(legend.position="bottom" ,
legend.direction="horizontal",
legend.title=theme_blank()) +
theme(legend.text=theme_text(size=7),
legend.background=theme_blank(),
legend.key=theme_blank())
The four lines on the plot are displayed in different linetypes, however the legend does not show these different linetypes only the different colours. I am obviously missing a very simple argument in theme() but I cannot figure out what it is. Maybe I need to specify the linetypes again in scale_colour_manual()?
Here's the data: https://dl.dropboxusercontent.com/u/22681355/proba.csv
proba<-read.csv("proba.csv",head=T)
Here, this is the correct way to do this in ggplot2:
proba <- read.csv("~/Downloads/proba.csv")
proba1 <- proba[108:140,]
proba1 <- melt(proba1,id.vars = 1:2)
ggplot(proba1,aes(x = c,y = value,colour = variable,linetype = variable,size = variable)) +
geom_line() +
scale_x_continuous(breaks=seq(110,140,5)) +
scale_colour_manual(values=c("blue3","blue3","red3","red3")) +
scale_linetype_manual(values = c(2,1,3,1)) +
scale_size_manual(values = c(0.2,0.3,0.8,0.6)) +
xlab("\nTime-steps") +
ylab("Proportion correct\n") +
theme_bw() +
theme(axis.text=element_text(size=6),
axis.title=element_text(size=8),
axis.line = element_line(size=0.25),
axis.ticks=element_line(size=0.25),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
legend.position="bottom" ,
legend.direction="horizontal",
legend.title=element_blank(),
legend.text=element_text(size=7),
legend.background=element_blank(),
legend.key=element_blank())
Try to keep all your theme adjustments in one call to theme, otherwise things get pretty messy. Also, you had some calls to theme_* that should have been element_*.
How can scatter plots with alpha transparent, scale-less histograms can be made in R, like this figure?
looks like it's not made in ggplot2.
does anyone know what command is used?
library(ggplot2)
library(gridExtra)
set.seed(42)
DF <- data.frame(x=rnorm(100,mean=c(1,5)),y=rlnorm(100,meanlog=c(8,6)),group=1:2)
p1 <- ggplot(DF,aes(x=x,y=y,colour=factor(group))) + geom_point() +
scale_x_continuous(expand=c(0.02,0)) +
scale_y_continuous(expand=c(0.02,0)) +
theme_bw() +
theme(legend.position="none",plot.margin=unit(c(0,0,0,0),"points"))
theme0 <- function(...) theme( legend.position = "none",
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.margin = unit(0,"null"),
axis.ticks = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.ticks.length = unit(0,"null"),
axis.ticks.margin = unit(0,"null"),
panel.border=element_rect(color=NA),...)
p2 <- ggplot(DF,aes(x=x,colour=factor(group),fill=factor(group))) +
geom_density(alpha=0.5) +
scale_x_continuous(breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(1,0,0,2.2),"lines"))
p3 <- ggplot(DF,aes(x=y,colour=factor(group),fill=factor(group))) +
geom_density(alpha=0.5) +
coord_flip() +
scale_x_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(0,1,1.2,0),"lines"))
grid.arrange(arrangeGrob(p2,ncol=2,widths=c(3,1)),
arrangeGrob(p1,p3,ncol=2,widths=c(3,1)),
heights=c(1,3))
Edit:
I couldn't find out what causes the space below the densities geoms. You can fiddle with the plot margins to avoid it, but I don't really like that.
p2 <- ggplot(DF,aes(x=x,colour=factor(group),fill=factor(group))) +
geom_density(alpha=0.5) +
scale_x_continuous(breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(breaks=NULL,expand=c(0.00,0)) +
theme_bw() +
theme0(plot.margin = unit(c(1,0,-0.48,2.2),"lines"))
p3 <- ggplot(DF,aes(x=y,colour=factor(group),fill=factor(group))) +
geom_density(alpha=0.5) +
coord_flip() +
scale_x_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(labels = NULL,breaks=NULL,expand=c(0.00,0)) +
theme_bw() +
theme0(plot.margin = unit(c(0,1,1.2,-0.48),"lines"))
I have no idea whether there is a package that does that directly, but I'm sure this can be done in R. Transparency is easy: you add another two digits to the RGB specification of a color for a given transparency:
#FF0000 # red
#FF0000FF # full opacity
#FF000000 # full transparency
Combining different plots is also easy using the layout function. As for the vertical density plot, it is just the same as the horizontal plot with x and y switched. The example given here can easily be expanded to include colors, smaller margins etc. I can try to come up with a more elaborate example if this description is not sufficient.