简体   繁体   English

在 R 中使用 ggplot 将 geom_tile 移动到绘图区域之外?

[英]Moving geom_tile outside of plotting area using ggplot in R?

I recently asked this question about plotting outside of the plot area using geom_tile and ggplot and I received an excellent answer.我最近问了这个关于使用geom_tileggplot在 plot 区域之外绘图的问题,我得到了一个很好的答案。 But I was wondering how I could tweak the results of the previous answer and manually move the extra bars that are being plotted.但我想知道如何调整前一个答案的结果并手动移动正在绘制的额外条。

For example, below is the code I'm using to create the plot.例如,下面是我用来创建 plot 的代码。 I'm using the patchwork package to add the extra geom_tile bars to outside of the plotting area, like so:我正在使用patchwork而成的 package 将额外的geom_tile条添加到绘图区域之外,如下所示:

library(colorspace)
library(ggplot2)
library(patchwork)
library(tidyverse)

# create data
df <- data.frame(
  a = paste0("a", c(1,1,1,2,2,2,3,3,3)),
  b = paste0("b", c(1,2,3,1,2,3,1,2,3)),
  c = c(-10, 3, 5, -2, 9, 1, -5, -2, 0)
)

# create some extra data to plot
extraBars <- rnorm(6)

# From discrete to continuous
df$a <- match(df$a, sort(unique(df$a)))
df$b <- match(df$b, sort(unique(df$b)))

# create labels
labels_a <- paste0("a", 1:length(df$a))
labels_b <- paste0("b", 1:length(df$b))

# set limits and colour palette 
intLims <- range(df$c)
limitsInt <- c(floor(intLims[1]), ceiling(intLims[2]))
intPal = rev(diverging_hcl(palette = "Blue-Red 3", n = 100))

# some preprcessing
NoOfa <- length(unique(df$a))
NoOfb <- length(unique(df$b))
NoOfd<- length(extraBars)

# main heatmap plot
p_main <- ggplot(df, aes(a, b)) +
  geom_tile(aes(fill = c)) +
  scale_y_continuous(breaks = c(1:length(labels_b)), labels = labels_b) +
  scale_x_continuous(breaks = c(1:length(labels_a)), labels = labels_a) +
  scale_fill_gradientn(
    limits = limitsInt,
    colors = intPal,
    guide = guide_colorbar(
      frame.colour = "black",
      ticks.colour = "black"
    ),
    name = "C"
  ) +
  theme_classic() +
  labs(x = "a", y = "b")



# bottom bar
p_bottom <- ggplot() +
  geom_tile(
    data = tibble(a = 1:NoOfa, extraBars = extraBars[(NoOfb + 1):NoOfd]),
    aes(x = a, y = 0, fill = extraBars)
  ) +
  scale_fill_gradientn(
    limits = limitsInt,
    colors = intPal,
    guide = guide_colorbar(
      frame.colour = "black", ticks.colour = "black"
    )
  ) +
  theme_void() +
  theme(legend.position = "none")

# left bar
p_left <- ggplot() +
  geom_tile(
    data = tibble(b = 1:NoOfb, extraBars = extraBars[1:NoOfb]),
    aes(x = 0, y = b, fill = extraBars)
  ) +
  scale_fill_gradientn(
    limits = limitsInt,
    colors = intPal,
    guide = guide_colorbar(
      frame.colour = "black",
      ticks.colour = "black"
    ),
    name = "extraBars"
  ) +
  theme_void()

# add them all together
p <- p_left + p_main + plot_spacer() + p_bottom +
  plot_layout(
    guides = "collect",
    heights = c(1, 0.07),
    widths = c(0.07, 1)
  )
p

This creates a plot like this:这将创建一个 plot ,如下所示: 热图

However, what I would like to do is to swap the extra bars around the edge with the axis title labels.但是,我想做的是将边缘周围的额外条与轴标题标签交换。 Below is a mock-up I created in photoshop to explain what Im trying to achieve:下面是我在 Photoshop 中创建的模型,用于解释我想要实现的目标:

改变的热图

I was wondering how I could achieve this?我想知道我怎么能做到这一点?

One approach you could use is to place your colored bars outside the plot with grobs (Grid Objects) and use annotation_custom to add them to the plot.您可以使用的一种方法是使用 grobs(网格对象)将彩色条放在 plot 之外,并使用annotation_custom将它们添加到 plot。 Using your example, I'll show you how you could do this.使用您的示例,我将向您展示如何做到这一点。 Just like your example, you would have to map the colors for the bars manually, but I'm not going to cover that here.就像您的示例一样,您必须手动为酒吧 map 和 colors ,但我不打算在这里介绍。 The purpose here is to only demonstrate how you would go about creating the grobs in general and adding them to the plot.此处的目的仅是演示如何 go 来创建一般的 grobs 并将它们添加到 plot。

In principle, it's pretty similar to the approach with patchwork .原则上,它与patchwork的方法非常相似。 First you want to define the grobs themselves, then you add them to the plot via annotation_custom() and fiddle with the positioning.首先,您要自己定义 grobs,然后通过annotation_custom()将它们添加到 plot 并调整定位。 It's hard to explain exactly how and where you should move them around - in my experience with grobs I find I have to fiddle quite a lot with exact placement.很难准确地解释你应该如何以及在哪里移动它们——根据我使用 grobs 的经验,我发现我必须在准确的位置上摆弄很多。 Here's the general code and result.这是一般代码和结果。

library(grid)
library(gridExtra)
library(ggpubr)   # we use the convenient text_grob() function from here

# define your grobs
bottom_grob <- rectGrob(x=1:3, y=1, gp=gpar( fill=rainbow(6)[1:3], alpha=0.5 ))
left_grob <- rectGrob(x=1, y=1:3, gp=gpar( fill=rainbow(6)[4:6], alpha=0.5 ))
bottom_textgrob <- text_grob(x=1:3, y=0,label=round(extraBars[1:3],2), size=10)
left_textgrob <- text_grob(x=1, y=1:3, label=round(extraBars[4:6],2), size=10, rot=90)

# add to the plot
the_plot <- 
  ggplot(df, aes(a, b)) +
  geom_tile(aes(fill = c)) +
  scale_y_continuous(breaks = c(1:length(labels_b)), labels = labels_b) +
  scale_x_continuous(breaks = c(1:length(labels_a)), labels = labels_a) +
  scale_fill_gradientn(
    limits = limitsInt,
    colors = intPal,
    guide = guide_colorbar(
      frame.colour = "black",
      ticks.colour = "black"
    ),
    name = "C"
  ) +
  theme_classic() +
  theme(
    axis.title.x = element_text(margin=margin(t=30)),
    axis.title.y = element_text(margin=margin(r=30))
  ) +
  labs(x = "a", y = "b") +
  coord_cartesian(clip="off") +
  annotation_custom(grob=left_grob, xmin=0.02, xmax=0.15, ymin=0, ymax=1) +
  annotation_custom(grob=bottom_grob, xmin=0, xmax=1, ymin=-0.1, ymax=0.1) +
  annotation_custom(grob=bottom_textgrob, xmin=0, xmax=1, ymin=0.1, ymax=0.1) +
  annotation_custom(grob=left_textgrob, xmin=0, xmax=0.15, ymin=0, ymax=1)

the_plot

在此处输入图像描述

A few important notes about the code above:关于上面代码的一些重要说明:

  • Note that you can provide vectors to the values for grob creation.请注意,您可以为创建 grob 的值提供向量。 We do this to create more than one rectangle by providing a vector of positions for x or y.我们这样做是为了通过为 x 或 y 提供一个位置向量来创建多个矩形。
  • I move the x axis title "down" and y axis title "to the left" by adding a margin to the theme element for each.通过为每个主题元素添加边距,我将 x 轴标题“向下”和 y 轴标题“向左”移动。 This gives space for the grob.这为 grob 提供了空间。
  • You must include turn off clipping by indicating clip="off" in one of the coord_* functions.您必须通过在coord_*函数之一中指示clip="off"来关闭剪辑。 This allows the stuff (grobs) to appear outside the panel of the plot (the place in-between the min and max x and y values).这允许东西(grobs)出现在 plot 的面板之外(最小和最大 x 和 y 值之间的位置)。

Rainbow colors are only used to demonstrate more clearly what's going on, but you might want to map those to the particular value associated with extraBars or another color scale. Rainbow colors 仅用于更清楚地演示发生了什么,但您可能希望 map 将那些与extraBars或其他色标相关的特定值。 What you see is that there is not a second legend... but honestly the extra legend makes things quite confusing in my mind.你看到的是没有第二个传说......但老实说,额外的传说让我的脑海里的事情变得相当混乱。 It's probably better to either make the outer bars all one color and/or just place the text value on top of them like I'm showing you here.最好将外栏全部设为一种颜色和/或将文本值放在它们上面,就像我在这里向您展示的那样。 I think it gets the same message across, but that's also a matter of opinion.我认为它传达了相同的信息,但这也是一个见仁见智的问题。

Hope this helps and gives you something to work from.希望这对您有所帮助并为您提供一些工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM