ggplot2
ggplot2 copied to clipboard
When setting "scales" in facet_grid, the horizontal justification of the axis labels shifts among the panels
Case1
Panel "F1" has 3 values and Panel "F2" has other 3 values. We use facet_grid without "scale" option, Axis Y of both panels has same 6 values. So, if we set "hjust = 0" in "element_text" on "axis.text.y", Text of Y axis are aligned left.
tibble(
F = c(rep("F1", 3), rep("F2", 3)),
Y = c("AAAAAAAAAAAAAAAAAAA", "BBBBB", "CCCCCCCCC", "DDDDD", "EEEEEEEE", "FFF"),
Cnt = c(10, 20, 30, 50, 40 ,60)
) %>%
ggplot(mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F)
) +
theme(
axis.text.y = element_text(hjust = 0)
)
Case2
Next, we add an option "scales = free_y" on facet_grid function, panel F1 and F2 has other values that have different width. So, the alignment position of the text varies depending on the panel.
tibble(
F = c(rep("F1", 3), rep("F2", 3)),
Y = c("AAAAAAAAAAAAAAAAAAA", "BBBBB", "CCCCCCCCC", "DDDDD", "EEEEEEEE", "FFF"),
Cnt = c(10, 20, 30, 50, 40 ,60)
) %>%
ggplot(mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F),
scales = "free_y"
) +
theme(
axis.text.y = element_text(hjust = 0)
)
Hi there, thanks for the report! To be clear, both axes have left-aligned text, it is just that there is additional space on the bottom axes due to misalignment with the top axis.
The issue occurs because the two guides are drawn independently of oneanother, unaware of dimensions of other axes in the same direction. Having dabbled a bit in the guide code, I can say with some confidence that it'll not be straightforward to line up the labels.
For example, when moving the label of a panel to the left side, I would like the Y-axis text to align along the panel.
tibble(
F = c(rep("F1", 3), rep("F2", 3)),
Y = c("AAAAAAAAAAAAAAAAAAA", "BBBBB", "CCCCCCCCC", "DDDDD", "EEEEEEEE", "FFF"),
Cnt = c(10, 20, 30, 50, 40 ,60)
) %>%
ggplot(mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F),
scales = "free_y",
switch = "y"
) +
theme(
axis.text.y = element_text(hjust = 0),
strip.text.y.left = element_text(angle = 0),
strip.placement = "outside"
)
Thanks, the intent is clear 👍 It is implementation-wise that this could be tricky.
in your case patchwork can help you doing what you want
library(patchwork)
library(ggplot2)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
dataggplot <- tibble(
F = c(rep("F1", 3), rep("F2", 3)),
Y = c("AAAAAAAAAAAAAAAAAAA", "BBBBB", "CCCCCCCCC", "DDDDD", "EEEEEEEE", "FFF"),
Cnt = c(10, 20, 30, 50, 40 ,60)
)
a1 <- ggplot(dataggplot %>%
filter(F=="F1"),
mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F),
scales = "free_y",
switch = "y"
) +
theme(
axis.text.y = element_text(hjust = 0),
strip.text.y.left = element_text(angle = 0),
strip.placement = "outside"
)+
coord_cartesian(xlim=c(NA,60))+
theme(axis.title.x = element_blank(),axis.ticks.x.bottom = element_blank(),
axis.text.x.bottom = element_blank())
a2 <- ggplot(dataggplot %>%
filter(F=="F2"),
mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F),
scales = "free_y",
switch = "y"
) +
theme(
axis.text.y = element_text(hjust = 0),
strip.text.y.left = element_text(angle = 0),
strip.placement = "outside"
)+
coord_cartesian(xlim=c(NA,60))
a1/a2 +
plot_layout(axis_titles = "collect_y")
Created on 2024-04-04 with reprex v2.1.0
@smouksassi I think the intent is to change the 'whitespace' area for the lower series of axis labels from left to right w.r.t the labels. That'd left-align all the y-axis labels. Like the following picture that I have expertly edited using MS paint:
@ujtwr please correct me if I'm misinterpreting the request
a quick fix would be to manually pad with spaces until you have a simiar strwidth this is not a solution but prevent you form needing to manually edit your plot
library(stringr)
library(ggplot2)
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
dataggplot <- tibble(
F = c(rep("F1", 3), rep("F2", 3)),
Y = c("AAAAAAAAAAAAAAAAAAA", "BBBBB", "CCCCCCCCC", "DDDDD", "EEEEEEEE",
"FFF "),
Cnt = c(10, 20, 30, 50, 40 ,60)
) %>%
mutate(Ypad= stringr::str_pad(Y, width = 20, side = "right",pad=" ",use_width=FALSE))
strwidth(dataggplot$Y)
#> Error in strwidth(dataggplot$Y): plot.new has not been called yet
ggplot(dataggplot,
mapping = aes(y = Y, x = Cnt)) +
geom_col() +
facet_grid(
rows = vars(F),
scales = "free_y",
switch = "y"
) +
theme(text = element_text(size=16),
axis.text.y = element_text(hjust = 0),
strip.text.y.left = element_text(angle = 0),
strip.placement = "outside"
)
Created on 2024-04-04 with reprex v2.1.0
@smouksassi Thank you for the suggestion. I have already tried it, but I'm a Japanese user, so sometimes there can be misalignment when padding with white spaces.