如何根据 ggplot2 绘制的图上的 y 轴值覆盖构面标签?

Posted

技术标签:

【中文标题】如何根据 ggplot2 绘制的图上的 y 轴值覆盖构面标签?【英文标题】:How to overlay facet labels according to y-axis value on plots made with ggplot2? 【发布时间】:2021-10-12 04:09:49 【问题描述】:

我创建了一个热图,表示两种产品(A 和 B)的使用时间,颜色为 C1 和 C2。根据使用时间,可以对产品的使用方式进行分类(上帝,常规或不良)。在使用分类中,有一些类别随着时间的变化而重叠,如下所述:

良好:使用时间大于或等于 280 分钟。

常规:使用时间在 150 到 350 分钟之间。

不好:使用时间小于或等于 10 分钟。

我想为好、常规和坏类别创建构面,而不是完全分离构面,而是将它们重叠,如下面的第二张图片所示。我所做的尝试并不令人满意。热图的最终美感不必与第二张图片中显示的完全相同,只需正确指示分类即可。

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

【问题讨论】:

【参考方案1】:

我认为没有任何方法可以使用现在存在的方面来解决这个问题。但是,您可以通过在比例尺中设置 coord_cartesian(clip = "off") 并使用正确的越界参数来在绘图区域之外使用文本注释一些矩形。不幸的是,这对连续 x 轴效果更好,但您当然可以制作“伪离散”比例。

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

由reprex package (v1.0.0) 于 2021-08-07 创建

【讨论】:

以上是关于如何根据 ggplot2 绘制的图上的 y 轴值覆盖构面标签?的主要内容,如果未能解决你的问题,请参考以下文章

python 如何绘制子图的同时绘制双坐标轴图像

使用 ggplot2 和 R 创建帕累托图

如何在条形图上更正 R 中 y 轴的比例和顺序

如何绘制这个有很多功能的图的图例?

如何绘制时间序列散点图,将缺失的 y 轴值显示为间隙?

如何使用plotly js在y轴上为单个x轴值(可能是日期)绘制两个点