Change the Position of the Strip Label in Ggplot from the Top to the Bottom

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 (deprecates switch).

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)

Sample Image

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)

Sample Image

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)

Sample Image

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 =
'Sepal.Length')
rather than x axis title.

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)

Sample Image

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.

Sample Image

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())

Sample Image

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.

Plot



Related Topics



Leave a reply



Submit