Change the position of the strip label in ggplot from the top to the bottom?
An answer for those searching in 2016.
As of ggplot2
2.0, the switch argument will do this for facet_grid
or facet_wrap
:
By default, the labels are displayed on the top and right of the plot. If "x", the top labels will be displayed to the bottom. If "y", the right-hand side labels will be displayed to the left. Can also be set to "both".
ggplot(...) + ... + facet_grid(facets, switch="both")
As of ggplot2 2.2.0,
Strips can now be freely positioned in
facet_wrap()
using the
strip.position argument (deprecatesswitch
).
Current docs, are still at 2.1, but strip.position
is documented on the dev docs.
By default, the labels are displayed on the top of the plot. Using strip.position it is possible to place the labels on either of the four sides by setting
strip.position = c("top", "bottom", "left", "right")
ggplot(...) + ... + facet_wrap(facets, strip.position="right")
Switching position of two facet strip labels and combine one label across columns
This could be easily done with ggh4x
package written by teunbrand:
Using facet_nested_wrap
function:
You can change which one you want to combine, just change the order in facet_nested_wrap
:
library(tidyverse)
#install.packages("ggh4x")
library(ggh4x)
dt %>%
ggplot(aes(x=generation, y= days))+
geom_bar(stat = "identity")+
facet_nested_wrap(~year + device_type, nrow = 1, ncol=4)
ggplot2, how can I change the position of strip labels or add a legend
The layout of facets can be more finely controlled using facet_wrap
and you can control the appearance of facet labels using the theme elements prefixed by strip
. See here for details.
Here is an example with your data that places the labels on top of the graphs and removes the shading, plus right justifies the text. I'm not sure if this is exactly what you are a looking for but it should give you the tools to adjust to your liking.
bartheme <- theme(panel.border = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.spacing.y=unit(1, "lines"),
axis.line = element_line(size = 1,colour = "black"),
axis.title = element_text(colour="black", size = rel(1.5)),
plot.title = element_text(hjust = 0.5, size=14),
plot.subtitle = element_text(hjust = 0.5,size=14),
panel.background = element_rect(fill="whitesmoke"),
axis.text = element_text(colour = "black", size = rel(1)),
strip.background = element_blank(),
strip.text = element_text(hjust = 1)
)
Bplot <-
ggplot(data = B, aes(x = Age, y = prop)) +
geom_bar(stat = 'identity', position = position_dodge(), fill = "dodgerblue") +
geom_text(aes(label = round(prop, 2)), vjust = -0.3, size = 3.5) +
facet_wrap(vars(River), ncol = 1) +
scale_y_continuous(limits=c(0,1), oob=rescale_none,expand=c(0,0))+
scale_x_continuous(breaks = c(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16))
Bplot + bartheme + ggtitle("Age distribution of white perch") + ylab("Proportion")
How to position strip labels in facet_wrap like in facet_grid
This does not seem easy, but one way is to use grid graphics to insert panel strips from a facet_grid plot into one created as a facet_wrap. Something like this:
First lets create two plots using facet_grid and facet_wrap.
dt <- txhousing[txhousing$year %in% 2000:2002 & txhousing$month %in% 1:3,]
g1 = ggplot(dt, aes(median, sales)) +
geom_point() +
facet_wrap(c("year", "month"), scales = "free") +
theme(strip.background = element_blank(),
strip.text = element_blank())
g2 = ggplot(dt, aes(median, sales)) +
geom_point() +
facet_grid(c("year", "month"), scales = "free")
Now we can fairly easily replace the top facet strips of g1
with those from g2
library(grid)
library(gtable)
gt1 = ggplot_gtable(ggplot_build(g1))
gt2 = ggplot_gtable(ggplot_build(g2))
gt1$grobs[grep('strip-t.+1$', gt1$layout$name)] = gt2$grobs[grep('strip-t', gt2$layout$name)]
grid.draw(gt1)
Adding the right hand panel strips need us to first add a new column in the grid layout, then paste the relevant strip grobs into it:
gt.side1 = gtable_filter(gt2, 'strip-r-1')
gt.side2 = gtable_filter(gt2, 'strip-r-2')
gt.side3 = gtable_filter(gt2, 'strip-r-3')
gt1 = gtable_add_cols(gt1, widths=gt.side1$widths[1], pos = -1)
gt1 = gtable_add_grob(gt1, zeroGrob(), t = 1, l = ncol(gt1), b=nrow(gt1))
panel_id <- gt1$layout[grep('panel-.+1$', gt1$layout$name),]
gt1 = gtable_add_grob(gt1, gt.side1, t = panel_id$t[1], l = ncol(gt1))
gt1 = gtable_add_grob(gt1, gt.side2, t = panel_id$t[2], l = ncol(gt1))
gt1 = gtable_add_grob(gt1, gt.side3, t = panel_id$t[3], l = ncol(gt1))
grid.newpage()
grid.draw(gt1)
ggplot: placing facet strips above axis title
This behaviour is generally desired. This becomes particularly clear when removing theme(strip.placement = 'outside')
. I personally feel that it is visually much clearer this way.
I also feel that you are possibly looking for a plot title (you could use labs(title =
rather than x axis title.
'Sepal.Length')
For your question, I guess one cannot get around messing with the grobs. Here one quick hack to simply swap the rows in the gtable
layout:
library(tidyverse)
library(gtable)
library(grid)
p <-
ggplot(iris)+
geom_bar(aes(x=Sepal.Length, y=Sepal.Width), stat="identity")+
facet_wrap(~Species, strip.position = "top") +
scale_x_continuous(sec.axis = dup_axis()) +
theme(strip.placement = "outside")
gp <- ggplotGrob(p)
# gp$layout #helps you to understand the gtable object
# gtable_show_layout(ggplotGrob(p)) #helps you to understand the gtable object
t_title <- gp$layout[gp$layout[['name']] == 'xlab-t' ,][['t']]
t_strip <- gp$layout[grepl('strip', gp$layout[['name']]),][['t']]
gp$layout[gp$layout[['name']] == 'xlab-t' ,][['t']] <- unique(t_strip)
gp$layout[gp$layout[['name']] == 'xlab-t' ,][['b']] <- unique(t_strip)
gp$layout[grepl('strip', gp$layout[['name']]),][['t']] <- t_title
gp$layout[grepl('strip', gp$layout[['name']]),][['b']] <- t_title
grid.newpage()
grid.draw(gp)
Created on 2020-02-06 by the reprex package (v0.3.0)
How to move x-axis labels from the top to the bottom when using facet_wrap?
The relevant options are strip.position = "bottom"
inside wrap, and strip.placement = "outside"
inside theme. In addition, if required, you can rename the facets inside wrap. See code below.
d <- read.table(text =
"Grp Var Col1 Col2 Col3
grp_1 8 46.8 50.0 50.6
grp_1 16 95.6 47.4 48.0
grp_1 24 45.1 45.6 46.4
grp_1 32 68.8 44.3 58.2
grp_1 40 44.6 52.2 44.3
grp_1 48 86.5 42.2 68.6
grp_2 40 63.2 95.6 63.0
grp_2 60 66.7 67.5 65.6
grp_2 80 69.6 70.7 67.9
grp_2 100 71.9 73.4 69.3
grp_2 120 73.8 75.7 48.0
grp_3 500 51.9 50.0 50.5
grp_3 1000 65.5 53.0 53.4
grp_3 5000 61.2 99.0 59.9
grp_3 10000 80.1 63.0 62.8
grp_3 30000 25.9 33.8 14.2
", header=T
)
library(ggplot2)
library(data.table)
d <- setDT(d)
dd <- melt(d, id.vars = c("Grp", "Var"), measure.vars = patterns(col="Col") )
ggplot(dd, aes(Var, value, color=variable)) +
geom_point() +
facet_wrap(~Grp,
scales = "free",
# comment out next line if renaming facets is not necessary
labeller = as_labeller(c(grp_1 = "Step 1", grp_2 = "Step 2", grp_3 = "Step 3") ),
strip.position = "bottom") +
xlab(NULL) +
theme(strip.background = element_blank(),
)
Change facet_wrap() strip positions to place facet strips inside plot
One option to achieve your desired result would be via the gggrid
package. Similar to ggplot2::annotation_custom
it allows to add grobs to a ggplot but offers much more flexibility, e.g. you could place different grobs to each facet panel. Moreover it allows to access the data
and coords
objects created by ggplot2 under the hood and allows to pass additional aesthetics.
Basically it requires a function which creates the grob which are then added to the ggplot via gggrid::grid_panel
. For the grob I use gridtext::richtext_grob
which makes it easy to add a strip text like text box to each panel.
library(ggplot2)
library(gggrid)
#> Loading required package: grid
library(gridtext)
set.seed(123)
ID <- rep(c("ABC123", "DEF456", "GHI789", "JKL012"), each = 10)
Vref <- c((runif(10, 1, 2)), (runif(10, 3, 5)), (runif(10, 6, 9)), (runif(10, 0, 2)))
Time <- rep(c(1:10), 4)
df <- data.frame(ID, Vref, Time)
tg <- function(data, coords) {
y_label <- max(coords$y)
gridtext::richtext_grob(data$label[which.max(coords$y)],
x = unit(0, "npc") + unit(.045, "npc"),
y = unit(y_label, "npc") + unit(2, "mm"),
hjust = 0,
vjust = 0,
valign = .5,
padding = unit(rep(4.4, 4), "pt"),
gp = grid::gpar(fontsize = 8, fill = "grey85"),
box_gp = grid::gpar(col = "grey85")
)
}
ggplot(df, aes(x = Time, y = Vref)) +
geom_col() +
scale_y_continuous(expand = expansion(mult = c(.05, .2))) +
facet_wrap(~ID, nrow = 2) +
gggrid::grid_panel(mapping = aes(label = ID), tg) +
theme(strip.text = element_blank())
ggplot2: change strip.text position in facet_grid plot
Here's one approach:
ggplot(tips, aes(x = total_bill, y = tip / total_bill)) +
geom_point() +
facet_grid(. ~ sex) +
geom_text(aes(label = sex), x = Inf, y = Inf, hjust = 1.5, vjust = 1.5) +
theme(
strip.background = element_blank(),
strip.text = element_blank()
)
However, this is not moving the strip.text
, rather, it's adding a geom_text
element and turning off the strip.background
and strip.text
, but I think it achieves the desired outcome.
Related Topics
Can't Loop with R's Leaflet Package to Produce Multiple Maps
Export Data Frames to Excel via Xlsx with Conditional Formatting
R Text File and Text Mining...How to Load Data
Finding Overlap in Ranges with R
R Command Line Passing a Filename to Script in Arguments (Windows)
Run Sweave or Knitr with Objects from Existing R Session
Non-Numeric Argument to Binary Operator Error in R
Select Columns Based on Multiple Strings with Dplyr Contains()
Why (Or When) Is Rscript (Or Littler) Better Than R Cmd Batch
What Does the @ Symbol Mean in R
Counting Non Nas in a Data Frame; Getting Answer as a Vector
R Data.Table Apply Function to Rows Using Columns as Arguments
Difference Between R-Base and R-Recommended Packages