I'm plotting some data using geom_rect; the x axis shows factor data, which has to be converted to numerical and padded in order to produce the rectangle. However, this means that the labels are also converted to numeric. Setting them manually using scale_x_discrete(labels())
just makes them disappear. How can I retain or add labels for the x axis?
library(ggplot2)
library(dplyr)
#sample data
dat <- data.frame(value=rnorm(100, mean=10, sd=1),
cat=c(rep('a', 50), rep('b', 25), rep('c', 25))) %>%
mutate(cat=factor(cat, levels=c('a', 'b', 'c')))
dat %>%
ggplot() +
geom_rect(aes(xmin=as.numeric(cat) - 0.2,
xmax=as.numeric(cat) + 0.2,
ymin = min(value),
ymax = max(value),
fill=cat),
color='white')
#scale_x_discrete(labels=c('a', 'b', 'c')) #makes x-axis labels disappear
Your rectangles have the wrong sizes, prepare their coordinates first with summarise
and mutate
. Then plot getting the labels from the original data.
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
#sample data
dat <- data.frame(value=rnorm(100, mean=10, sd=1),
cat=c(rep('a', 50), rep('b', 25), rep('c', 25))) %>%
mutate(cat=factor(cat, levels=c('a', 'b', 'c')))
dat %>%
summarise(
ymin = min(value),
ymax = max(value),
.by = cat
) %>%
mutate(
xmin = as.integer(cat) - 0.2,
xmax = as.integer(cat) + 0.2
) %>%
ggplot() +
geom_rect(aes(xmin = xmin,
xmax = xmax,
ymin = ymin,
ymax = ymax,
fill = cat),
color='white') +
scale_x_continuous(breaks = 1:3, labels = unique(dat$cat))
Created on 2025-06-16 with reprex v2.1.1
The x axis breaks and labels can (and should) also be obtained in advance.
lbls <- unique(dat$cat)
brks <- seq_along(lbls)
Then use
scale_x_continuous(breaks = brks, labels = lbls)