How to remove the margin between plot region and panel in ggplot2? - r

I am creating some maps and want to remove all margins between the plot region and panel border.
This is the minimal example to reproduce my question
library(ggplot2)
library(grid)
df <- expand.grid(list(x = seq(1, 10), y = seq(1, 10), z = seq(1, 2)))
p <- ggplot(df) + geom_tile(aes(x, y)) + facet_wrap(~z)
p <- p + theme_minimal() + xlab('') + ylab('')
p <- p + theme(axis.text = element_blank(),
panel.grid = element_blank(),
axis.ticks = element_blank(),
panel.border = element_rect(colour = 'black', fill = 'transparent'),
panel.margin = unit(0, 'mm'))
p + ylim(2, 6) + xlim(2, 6)
This is the result of my codes.
How could I remove all white areas in the figure above? Thanks for any suggestions.

(Alright, here's my comment as an answer..)
Just add the following to the plot:
+ scale_y_continuous(expand = c(0,0)) + scale_x_continuous(expand = c(0,0))

Related

Center-align shared y-axis text between plots

I have the following dummy data and plots:
library(ggplot2)
library(patchwork)
test_data <- data.frame(sample = c("sample1_long_label","sample2","sam3","sample4_long_labels_are_annoying"),
var1 = c(20,24,19,21),
var2 = c(4000, 3890, 4020, 3760))
p1 <- ggplot(test_data, aes(var1, sample)) +
geom_col() +
scale_x_reverse() +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank())
p2 <- ggplot(test_data, aes(var2, sample)) +
geom_col() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank())
p1 + p2
This creates a plot that looks like this:
Now, the y-axis labels are right-aligned to the right plot (they have been removed in the left plot). I would like the y-axis labels to be center-aligned between the two plots. Is this possible? If not, any other method that will create a similar plot is welcome.
Edit: I forgot to mention that the labels may be of different lengths, and have adjusted the test data. Is it possible to make the whole label visible in the center while center-adjusting the text?
I think it might be easiest to control the spacing through the y-axis text margin, and discard any other margins or spacing. To do this:
Set the right margin of the left plot to 0
Set the left margin of the right plot to 0
Set the tick length of the right plot to 0. Even though these are blank, still space is reserved for them.
Set the right and left margins of the axis text of the right plot.
In the code below, 5.5 points is the default margin space, but feel free to adjust that to personal taste.
library(ggplot2)
library(patchwork)
test_data <- data.frame(sample = c("sample1","sample2","sample3","sample4"),
var1 = c(20,24,19,21),
var2 = c(4000, 3890, 4020, 3760))
p1 <- ggplot(test_data, aes(var1, sample)) +
geom_col() +
scale_x_reverse() +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank(),
plot.margin = margin(5.5, 0, 5.5, 5.5))
p2 <- ggplot(test_data, aes(var2, sample)) +
geom_col() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.ticks.length = unit(0, "pt"),
plot.margin = margin(5.5, 5.5, 5.5, 0),
axis.text.y.left = element_text(margin = margin(0, 5.5, 0, 5.5)))
p1 + p2
Created on 2022-01-31 by the reprex package (v2.0.1)
EDIT: To center align labels with various lengths, you can use hjust as per usual: axis.text.y.left = element_text(margin = margin(0, 5.5, 0, 5.5), hjust = 0.5).
A second option would be to add the axis labels via a third plot:
library(ggplot2)
library(patchwork)
test_data <- data.frame(sample = c("sample1","sample2","sample3","sample4"),
var1 = c(20,24,19,21),
var2 = c(4000, 3890, 4020, 3760))
p1 <- ggplot(test_data, aes(var1, sample)) +
geom_col() +
scale_x_reverse() +
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank())
p2 <- ggplot(test_data, aes(var2, sample)) +
geom_col() +
theme(axis.text.y = element_blank(),
axis.title.y = element_blank(),
axis.ticks.y = element_blank())
p3 <- ggplot(test_data, aes(1, sample)) +
geom_text(aes(label = sample)) +
scale_x_reverse() +
theme_void()
p1 + p3 + p2 +
plot_layout(widths = c(4, 1, 4))

Add a specific color to each tile and a legend in geom_tile

I want to add two things to the following figure:
add a legend (zp or df$legend) (which is similar to each block) to the geom_tile figure
assign a specific color to each tile (which repeats for every block) instead of scale_fill_continuous but keep the "white" color for NA values.
library(ggplot2)
library(RColorBrewer)
xp <- c('Disease_1','Disease_2','Disease_3','Disease_4')
yp <- c('B Cell','T Cell')
zp <- c('feature1','feature2','feature3','feature4','feature5','feature6','feature7','feature8')
xp1 <- xp[1:2]
df <- list(x=1:2,y=1:4,xp1,yp)
df <- expand.grid(df)
df$z <- c(1.804344554,1.158037086,1.686173307,0.500280283,1.710806067,0.857513435,0.66474755,1.164780941,1.769090931,2.058400169,3.114233859,1.436684123,1.770306398,0.995507604,2.538556363,2.264486118,1.424789875,1.816608927,2.773082903,1.197434618,0.829416784,1.622892741,2.035117094,1.650363345,1.927235048,1.546477438,2.308773122,1.041881013,1.216029616,0.478353441,0.834348006,1.240448774)
df$legend <- rep(c('feature1','feature2','feature3','feature4','feature5','feature6','feature7','feature8'))
cols <- rev(brewer.pal(11, 'RdYlBu'))
p <- ggplot(df)
p <- p + geom_tile(aes(x, y, fill = ifelse(z > 1, z, NA)),
colour = "black", width=0.85, height=0.85, size=1) +
scale_fill_continuous(name = "z Scale", na.value = 'white') +
labs() +
facet_grid(Var3~Var4) +
theme(strip.background =element_blank(), #remove bg color of facet_grid texts
strip.text.x = element_text(size=12, color="black", face="bold"),
strip.text.y = element_text(size=10, color="black", face="bold"))
print(p)
p + coord_fixed() +
theme(
axis.title = element_blank(),
axis.text=element_blank(),
axis.ticks=element_blank(),
plot.background=element_blank(),
panel.border=element_blank(),
panel.background = element_blank())
Thanks in advance.

How to avoid axis line disappearing when using ggarrange?

I'd like to arrange two facet plots using ggarrange (in order to get x axes aligned).
library(egg)
library(ggplot2)
p1 <- ggplot(warpbreaks) +
geom_bar(aes(x = wool)) +
facet_wrap(~tension, ncol = 2, scales = "free_x") +
theme_bw() +
theme(axis.line = element_line(colour = "black", size = .1),
panel.border = element_blank(),
strip.background = element_blank())
p2 <- ggplot(warpbreaks) +
geom_bar(aes(x = tension)) +
facet_wrap(~wool) +
theme_bw() +
theme(axis.line = element_line(colour = "black", size = .1),
panel.border = element_blank(),
strip.background = element_blank())
ggarrange(p1, p2, ncol = 2)
Works great, but unfortunately the vertical axis lines disappeared. This does not happen when using grid.arrange, but at least for my real data there the x axes are not aligned, hence my wish to use ggarrange. Is there a way to keep the axis lines?
tl;dr: setting panel.background = element_blank() should restore the axes.
I think it's a combination of a clipping issue in ggplot2 (the y axis line can be clipped by the plot panel, cutting its width in half), and egg::gtable_frame placing the axis below the plot panel.
library(egg)
library(ggplot2)
p1 <- ggplot(warpbreaks) +
geom_bar(aes(x = wool)) +
facet_wrap(~tension, ncol = 2, scales = "free_x") +
theme_bw() +
theme(axis.line = element_line(colour = alpha("red", 0.5), size = 5),
panel.border = element_blank(),
panel.background = element_rect(fill = alpha("white", 0.5),
linetype = 2, colour = "black"),
strip.background = element_blank())
p1
g1 <- ggplotGrob(p1)
gg <- gtable_frame(g1)
grid.newpage()
grid.draw(gg)

ggplot2: Make the filled area of the spatial plot flush with facet strip [duplicate]

I am creating some maps and want to remove all margins between the plot region and panel border.
This is the minimal example to reproduce my question
library(ggplot2)
library(grid)
df <- expand.grid(list(x = seq(1, 10), y = seq(1, 10), z = seq(1, 2)))
p <- ggplot(df) + geom_tile(aes(x, y)) + facet_wrap(~z)
p <- p + theme_minimal() + xlab('') + ylab('')
p <- p + theme(axis.text = element_blank(),
panel.grid = element_blank(),
axis.ticks = element_blank(),
panel.border = element_rect(colour = 'black', fill = 'transparent'),
panel.margin = unit(0, 'mm'))
p + ylim(2, 6) + xlim(2, 6)
This is the result of my codes.
How could I remove all white areas in the figure above? Thanks for any suggestions.
(Alright, here's my comment as an answer..)
Just add the following to the plot:
+ scale_y_continuous(expand = c(0,0)) + scale_x_continuous(expand = c(0,0))

Overlay different datasets in same facetted plot in ggplot2

I need to gather two facet columns into one column with ggplot2.
In the following example, I need to overlay the content of the two columns DEG and RAN into one, while giving different colours to DEG and RAN data (small points and smooth line) and provide the corresponding legend (so I can distinguish them as they are overlayed).
I feel my code is not too, too far from what I need, but the relative complexity of the dataset blocks me. How to go about achieving this in ggplot2?
Here's my code so far:
require(reshape2)
library(ggplot2)
library(RColorBrewer)
fileName = paste("./4.csv", sep = "") # csv file available here: https://www.dropbox.com/s/bm9hd0t5ak74k89/4.csv?dl=0
mydata = read.csv(fileName,sep=",", header=TRUE)
dataM = melt(mydata,c("id"))
dataM = cbind(dataM,colsplit(dataM$variable,pattern = "_",names = c("NM", "ORD", "CAT")))
dataM$variable <- NULL
dataM <- dcast(dataM, ... ~ CAT, value.var = "value")
my_palette <- colorRampPalette(rev(brewer.pal(11, "Spectral")))
ggplot(dataM, aes(x=NR ,y= ASPL)) +
geom_point(size = .4,alpha = .5) +
stat_smooth(se = FALSE, size = .5) +
theme_bw() +
theme(plot.background = element_blank(),
axis.line = element_blank(),
legend.key = element_blank(),
legend.title = element_blank()) +
scale_y_continuous("ASPL", expand=c(0,0), limits = c(1, 7)) +
scale_x_continuous("NR", expand=c(0,0), limits = c(0, 100)) +
theme(legend.position="bottom") +
theme(axis.title.x = element_text(vjust=-0.3, face="bold", size=12)) +
theme(axis.title.y = element_text(vjust=1.5, face="bold", size=12)) +
ggtitle("Title") + theme(plot.title = element_text(lineheight=.8, face="bold")) +
theme(title = element_text(vjust=2)) +
facet_grid(NM ~ ORD)
Here's what it gives me right now:
Extra question: how come DEG/SF doesn't show a smooth line?
You can use the group aesthetic to define that data points with the same value of ORD belong together. You can also map aesthetics shape and color to this variable. You can also use . to specify that the facets are not split along a specific dimension.
I have made the changes to your code below after transforming NR and ASPL to numeric variables:
dataM$NR <- as.integer(dataM$NR)
dataM$ASPL <- as.numeric(dataM$ASPL)
ggplot(dataM, aes(x=NR ,y= ASPL, group=ORD, color=ORD)) +
geom_point(size = .7,alpha = .5, aes(shape=ORD)) + ## increased size
stat_smooth(se = FALSE, size = .5) +
theme_bw() +
theme(plot.background = element_blank(),
axis.line = element_blank(),
legend.key = element_blank(),
legend.title = element_blank()) +
scale_y_continuous("ASPL", expand=c(0,0), limits = c(1, 7)) +
scale_x_continuous("NR", expand=c(0,0), limits = c(0, 100)) +
theme(legend.position="bottom") +
theme(axis.title.x = element_text(vjust=-0.3, face="bold", size=12)) +
theme(axis.title.y = element_text(vjust=1.5, face="bold", size=12)) +
ggtitle("Title") + theme(plot.title = element_text(lineheight=.8, face="bold")) +
theme(title = element_text(vjust=2)) +
facet_grid(NM ~.)

Resources