I would like to create facet_grid / facet_wrap plot with the x axis being repeated under each graph but with ticks present only on the lowest graph.
Here is an example of a plot with the x axis present only once using facet_grid
ggplot(mtcars, aes(y=mpg,x=cyl)) +
facet_grid(am~., scales="free") +
geom_point() +
theme_classic() +
theme(strip.background = element_rect(colour="white", fill="white"),
strip.text.y = element_blank())
Here is an example of a plot with the x axis present twice but with ticks both times using facet_wrap
ggplot(mtcars, aes(y=mpg, x=cyl)) +
facet_wrap(~am, ncol=1, scales="free") +
geom_point() +
theme_classic() +
theme(strip.background = element_rect(colour="white", fill="white"),
strip.text.x = element_blank())
I would like the same plot as the one just above but without the ticks on the x-axis of the upper graph. Or if you prefer, I would like the same plot as the first one but with an x-axis on the upper graph.
This is a very verbose solution, but I don't think you can get the plot you want using just the usual ggplot functions.
library(ggplot2)
library(grid)
Plot <- ggplot(mtcars, aes(y=mpg, x=cyl)) +
facet_wrap(~am, ncol=1, scales="free") +
geom_point() +
theme_classic() +
theme(strip.background = element_rect(colour="white", fill="white"),
strip.text.x = element_blank())
Switching off the top x-axis requires modifying the gtable object for the plot.
Plot.build <- ggplot_gtable(ggplot_build(Plot))
axis.pos <- grep("axis-b-1-1", Plot.build$layout$name)
num.ticks <- length(Plot.build$grobs[[axis.pos]]$children[2]$axis$grobs[[1]]$y)
This step removes the axis labels:
Plot.build$grobs[[axis.pos]]$children$axis$grobs[[2]]$children[[1]]$label <- rep("", num.ticks)
This step removes the tick marks:
Plot.build$grobs[[axes.pos]]$children[2]$axis$grobs[[1]]$y <- rep(unit(0, units="cm"), num.ticks)
Finally, the plot is generated using:
grid.draw(Plot.build)
The workaround I use to get just an axis line (no tick marks) is to use geom_hline() to fake an axis.
#make a dataframe with the y minimum for each facet
fake.axes <- data.frame(mpg = c(10, 15), #y minimum to use for axis location
am = c(0,1)) #facetting variable
#add an "axis" without ticks to upper graph using geom_hline()
ggplot(mtcars, aes(y=mpg,x=cyl)) +
facet_grid(am~., scales="free") +
geom_point() +
geom_hline(aes(yintercept = mpg), fake.axes, #dataframe with fake axes
linetype = c("solid", "blank")) + #line for top graph, blank for bottom graph
theme_classic() +
theme(strip.background = element_rect(colour="white", fill="white"),
strip.text.y = element_blank())
If you haven't used scales = "free", and all the axes are in the same location this is even simpler, you can skip making a dataframe with yintercepts for each facet and simply add
geom_hline(yintercept = 10) (or whatever your minimum is) to your plot code to add an axis line on each facet.
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'm currently using the qqman R package to create Manhattan plot:
library(qqman)
manhattan(gWasResults,cex.axis = 0.5)
But I want to change all of the colors in each chromosome to black like this:
manhattan(gWasResults,col = c("black","black"),cex.axis = 0.5)
If I want to add spacing between each chromosome so that you can distinguish which column of data/ or datapoints belongs to which chromosome, is there a specific plot argument I can specify in the Manhattan module to do this (see for example image below)?
An alternative would be to use ggplot2. Actually, the example graph that you gave for a desired output seems created with ggplot2.
Here are two solutions:
a) Using jittering - geom_jitter
library(qqman)
library(ggplot2)
ggplot(data = gwasResults,
aes(x = as.factor(CHR),
y = -log10(P))) +
geom_jitter(width = 0.2) + # adjusting width, impacts the spacing
labs(x = "CHR") +
# remove space between plot area and x axis
scale_y_continuous(expand = c(0, 0.1))
b) Using faceting - facet_grid
ggplot(data = gwasResults,
aes(x = BP,
y = -log10(P))) +
geom_point() +
# remove space between plot area and x axis
scale_y_continuous(expand = c(0, 0.1)) +
# facet by CHR
facet_grid(cols = vars(CHR),
space = "free_x",
scales = "free_x",
switch = "x") +
labs(x = "CHR") +
theme(
axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
panel.grid = element_blank(),
panel.spacing = unit(0.1, "cm") # adjust spacing between facets
)
I have this code for a dendrogram. How can I decrease the size of dendrogram (or y-axis)?
I am using this code as example. In my dataset, I have large labels so I do not have space enough to include it. For that reason, I would like to reduce the space used for y axis, decrease the distance between 0 and 150. Also, when I save the figure as tiff, most of figure is the dendogram and I can not see labels clearly.
df <- USArrests # really bad idea to muck up internal datasets
labs <- paste("sta_",1:50,sep="") # new labels
rownames(df) <- labs # set new row names
library(ggplot2)
library(ggdendro)
hc <- hclust(dist(df), "ave") # heirarchal clustering
dendr <- dendro_data(hc, type="rectangle") # convert for ggplot
clust <- cutree(hc,k=2) # find 2 clusters
clust.df <- data.frame(label=names(clust), cluster=factor(clust))
# dendr[["labels"]] has the labels, merge with clust.df based on label column
dendr[["labels"]] <- merge(dendr[["labels"]],clust.df, by="label")
# plot the dendrogram; note use of color=cluster in geom_text(...)
ggplot() +
geom_segment(data=segment(dendr), aes(x=x, y=y, xend=xend, yend=yend)) +
geom_text(data=label(dendr),
aes(x, y, label=label, hjust=0, color=cluster),
size=3) +
coord_flip() +
scale_y_reverse(expand=c(0.2, 0)) +
theme(axis.line.y=element_blank(),
axis.ticks.y=element_blank(),
axis.text.y=element_blank(),
axis.title.y=element_blank(),
panel.background=element_rect(fill="white"),
panel.grid=element_blank())
How can I decrease the size of dendogram similar than this heatmap?
(source: r-graph-gallery.com)
Thanks you so much
For flexibility, I recommend putting the dendrogram labels on the x-axis itself, rather than text labels within the plot. Otherwise no matter what values you choose for expand in the y-axis, part of the labels could be cut off for some image sizes / dimensions.
Define colour palette for the dendrogram labels:
library(dplyr)
label.colour = label(dendr)$cluster %>%
factor(levels = levels(.),
labels = scales::hue_pal()(n_distinct(.))) %>%
as.character()
For the purpose of illustration, make some labels very long:
label.values <- forcats::fct_recode(
label(dendr)$label,
sta_45_abcdefghijklmnop = "sta_45",
sta_31_merrychristmas = "sta_31",
sta_6_9876543210 = "sta_6")
Plot:
p <- ggplot(segment(dendr)) +
geom_segment(aes(x=x, y=y, xend=xend, yend=yend)) +
coord_flip() +
scale_x_continuous(breaks = label(dendr)$x,
# I'm using label.values here because I made
# some long labels for illustration. you can
# simply use `labels = label(dendr)$label`
labels = label.values,
position = "top") +
scale_y_reverse(expand = c(0, 0)) +
theme_minimal() +
theme(axis.title = element_blank(),
axis.text.y = element_text(size = rel(0.9),
color = label.colour),
panel.grid = element_blank())
p
# or if you want a color legend for the clusters
p + geom_point(data = label(dendr),
aes(x = x, y = y, color = cluster), alpha = 0) +
scale_color_discrete(name = "Cluster",
guide = guide_legend(override.aes = list(alpha = 1))) +
theme(legend.position = "bottom")
You can do this by adding a size parameter to axis.text.y like so:
theme(axis.line.y=element_blank(),
axis.ticks.y=element_blank(),
axis.text.y=element_text(size=12),
axis.title.y=element_blank(),
panel.background=element_rect(fill="white"),
panel.grid=element_blank())
I'd like to display x-axis ticks on plots in the upper rows in facet_wraps. For example:
library(ggplot2)
ggplot(diamonds, aes(carat)) + facet_wrap(~ cut, scales = "fixed") + geom_density()
generates this plot:
I'd like to have ticks as I've drawn in on this plot:
Is there a simple way to achieve this result?
Using scales = "free_x" adds x axes to each plot:
ggplot(diamonds, aes(carat)) +
geom_density() +
facet_wrap(~cut, scales = "free_x")
However, as you can see and the syntax suggests, it also frees the limits of each plot to adjust automatically, so if you want them all to be consistent, you'll need to set them with xlim, lims or scale_x_continuous:
ggplot(diamonds, aes(carat)) +
geom_density() +
xlim(range(diamonds$carat)) +
# or lims(x = range(diamonds$carat))
# or scale_x_continuous(limits = range(diamonds$carat))
facet_wrap(~cut, scales = "free_x")
Please consider the following
library(ggplot)
data <- data.frame(qnt=c(10,20,22,12,14,9,1000),lbl=c("A","B","C","D","E","F","G"))
ggplot(data=data, aes(x=lbl, y=qnt)) + geom_histogram(stat="identity")
which produces
Which options should I consider to truncate the highest bar G in the plot? (of course explaining to the viewer what I did)
If you want to fiddle with it, you can use the gridExtra package, and plot 2 (or more) trimmed out sections of the graph. I've tinkered with the margins to make it line up, but a better plan would probably be to format the axis labels to the same text width,
require(ggplot2)
require(gridExtra)
data <- data.frame(qnt=c(10,20,22,12,14,9,1000),lbl=c("A","B","C","D","E","F","G"))
g1<-ggplot(data=data, aes(x=lbl, y=qnt)) +
geom_histogram(stat="identity")+
coord_cartesian(ylim=c(-10,50)) +
labs(x=NULL, y=NULL)+
theme(plot.margin=unit(c(2,2,6,3),"mm"))
g2<-ggplot(data=data, aes(x=lbl, y=qnt)) +
geom_histogram(stat="identity") +
coord_cartesian(ylim=c(990,1010)) +
theme(axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.ticks.x = element_blank()) +
labs(x=NULL, y=NULL) +
theme(plot.margin=unit(c(5,2,0,0),"mm"))
grid.arrange(g2,g1, heights=c(1/4, 3/4), ncol=1, nrow=2)
You can use coord_cartesian() and change limits for the y axis - coord_cartesian() will "zoom" the plot to the limits you will provide. Also I used geom_bar() as your are plotting factors on x axis.
ggplot(data=data, aes(x=lbl, y=qnt)) + geom_bar(stat="identity")+
coord_cartesian(ylim=c(0,100))
Another possibility is to use logarithm scale for y values.
ggplot(data=data, aes(x=lbl, y=qnt)) + geom_bar(stat="identity")+
scale_y_log10()