Reputation: 2279
I created a heat map that represents the usage time of two products (A and B) that are available in colors C1 and C2. According to the time of use, it is possible to classify how the product was used (God, regular or bad). Within the usage classification there are categories that overlap as a function of time, as described below:
Good: use time greater than or equal to 280 minutes.
Regular: use time between 150 and 350 minutes.
Bad: use time less than or equal to 10 minutes.
I want to create facets for the categories good, regular and bad, without completely separating the facets but overlapping them as shown in the second image below. The attempts I've made have been unsatisfactory. The final aesthetics of the heat map need not be exactly the same as the one shown in the second image, what is necessary is to correctly indicate the classification.
library(ggplot2)
Product <- c("A", "B")
Color <- c("C1", "C2")
Time <- seq(10, 430, 60)
df <- expand.grid(Time = Time,
Color = Color,
Product = Product)
df$Fill_factor <- seq(1, 32, 1)
df$Usage <- ifelse(
df$Time <= 10,
"Bad",
ifelse(
df$Time >= 150 & df$Time <= 350,
"Regular",
ifelse(
df$Time >= 280,
"Good",
"Without classification"
)
)
)
ggplot(data = df,
aes(x = Product,
y = Time,
fill = Fill_factor)) +
geom_tile() +
geom_text(aes(label = Fill_factor),
size = 2.5) +
facet_grid(~ Color) +
scale_y_continuous(breaks = seq(10, 430, 60))
# Fail
ggplot(data = df,
aes(x = Product,
y = Time,
fill = Fill_factor)) +
geom_tile() +
geom_text(aes(label = Fill_factor),
size = 2.5) +
facet_grid(Usage ~ Color) +
scale_y_continuous(breaks = seq(10, 430, 60))
Upvotes: 0
Views: 173
Reputation: 37963
I don't think there is any way to solve this using facets as they exist now. However, you can annotate a few rectangles with text outside the plotting area by setting coord_cartesian(clip = "off")
with the right out-of-bounds argument in the scales. Unfortunately, this works better with a continuous x-axis, but you can of course make 'pseudodiscrete' scales.
library(ggplot2)
Product <- c("A", "B")
Color <- c("C1", "C2")
Time <- seq(10, 430, 60)
df <- expand.grid(Time = Time,
Color = Color,
Product = Product)
df$Fill_factor <- seq(1, 32, 1)
# Make annotation data.frame
max_x <- (length(unique(df$Product)) + 0.6)
anno <- data.frame(
Color = "C2",
Usage = c("Good", "Regular", "Bad"),
xmin = max_x,
xmax = max_x + c(0.5, 0.25, 0.25),
ymin = c(280, 160, -20),
ymax = c(460, 340, 40)
)
ggplot(data = df,
aes(x = match(Product, sort(unique(Product))),
y = Time,
fill = Fill_factor)) +
geom_tile() +
geom_text(aes(label = Fill_factor),
size = 2.5) +
# Adding the rectangles from annotation data
geom_rect(
data = anno,
aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
fill = c("limegreen", "gold", "tomato"),
inherit.aes = FALSE
) +
# Adding text from annotation data
geom_text(
data = anno,
aes(x = (xmin + xmax) / 2, y = (ymin + ymax) / 2,
label = Usage),
inherit.aes = FALSE, angle = 270
) +
facet_grid(~ Color) +
scale_y_continuous(breaks = seq(10, 430, 60)) +
# Set breaks and labels as they would be for discrete scale
scale_x_continuous(limits = c(0.5, 2.5),
breaks = seq_along(unique(df$Product)),
labels = sort(unique(df$Product)),
oob = scales::oob_keep) +
coord_cartesian(clip = "off") +
theme(legend.box.margin = margin(l = 40))
Created on 2021-08-07 by the reprex package (v1.0.0)
Upvotes: 1