如何为这个 ggplot2 脚本定义和添加图例?

How can I define and add a lagend to this ggplot 2 script?

我想出了以下脚本来对 X 值上的数据进行分箱,并在重叠条形图中绘制这些分箱的均值。它工作正常,但我似乎无法生成图例,可能是由于对美学映射的理解不足。

这里是脚本,注意“MOI”和“T_cell_contacts”是每个DF中的两个数据列。

ggplot(mapping=aes(MOI, T_cell_contacts))  +   stat_summary_bin(data = Cleaned24hr4, fun = "mean", geom="bar", bins= 100, fill = "#FF6666", alpha = 0.3) + stat_summary_bin(data = cleaned24hr8, fun = "mean", geom="bar", bins= 100, fill = "#3733FF", alpha = 0.3) +   ylab("mean")

我还添加了它绘制的图表。

我认为困难在于用两个不同的 geom 构建一个图例。我的方法是将您的数据合并到一个数据框中。每个记录都被一个新的类别列分开,我将简称为“猫”。 使用流行的 dplyr 包:

Cleaned24hr4 <- mutate(Cleaned24hr4, cat = "hr4")
Cleaned24hr8 <- mutate(Cleaned24hr8, cat = "hr8")

然后把它们放在一起:

Cleaned <- union(Cleaned24hr4,Cleaned24hr8)

定义你的颜色:

colorcode <- c("hr4" = "#FF6666", "hr8" = "#3733FF")

这是我的 ggplot 语句:

ggplot(Cleaned, mapping=aes(MOI, T_cell_contacts)) +
  stat_summary_bin(fun = "mean", geom="bar", bins= 100, aes(fill = cat), alpha = 0.3) +
  scale_fill_manual(values = colorcode) +
  ylab("mean")

使用一些虚拟数据输出。

完全披露:当@schumacher 发布他们的回复时,我正在写这篇文章:)。无论如何决定完成。

有两种方法可以解决这个问题。一种方法(更复杂)是将数据帧分开并要求 ggplot2 通过映射创建图例,第二种(更简单)方法是合并成一个类似于@schumacher 发布的数据集并映射填充颜色到创建的额外 id 列。

我会向你们展示,但首先,这是一个示例数据集:

library(ggplot2)
set.seed(8675309)
df1 <- data.frame(my_x=rep(1:100, 3), my_y=rnorm(300, 40, 4))
df2 <- data.frame(my_x=rep(11:110, 3), my_y=rnorm(300, 110, 10))

# and the plot code similar to OP's question
ggplot(mapping=aes(x = my_x, y = my_y)) +
  stat_summary_bin(data=df1, fun="mean", geom="bar", bins=40, fill="blue", alpha=0.3) +
  stat_summary_bin(data=df2, fun="mean", geom="bar", bins=40, fill="red", alpha=0.3)

方法 1:合并数据帧

这是首选 方法,由于多种原因我无法在此一一列举。您可以使用很多选项来组合数据集。一种是在向数据添加某种 ID 列后使用 union()rbind(),但您可以使用 dplyr:[=52= 中的 bind_rows() 一次完成所有操作]

df <- dplyr::bind_rows(list(dataset1 = df1, dataset2 = df2), .id="id")

结果会将行绑定在一起并通过指定 .id 参数,它将在名为 "id" 的数据集中创建一个新列,该列使用列表中每个数据集的名称作为价值。在这种情况下,thd df$id 列中的值是 "dataset1" 如果它源自 df1"dataset2" 如果它源自 df2.

然后使用 aes(fill=...) 将填充颜色映射到组合数据集中的列 "id"

p <- ggplot(df, aes(x=my_x, y=my_y)) +
  stat_summary_bin(aes(fill=id), fun="mean", geom="bar", bins=40, alpha=0.3)
p

这将使用 fill 的默认颜色创建绘图,因此如果您想提供自己的颜色,只需使用 scale_fill_manual(values=...) 指定特定颜色即可。为 values= 使用命名向量可确保按您希望的方式应用每种颜色,但您可以只提供一个未命名的颜色名称向量。

p + scale_fill_manual(values = c("dataset1" = "blue", "dataset2" = "red"))

方法二:使用映射添加图例

虽然首选方法 1,但还有另一种方法不会强制您合并数据帧。这也有助于说明 ggplot2 如何决定创建和绘制图例。图例是通过 mapping= 参数自动创建的,特别是通过 aes()。如果你在 aes() 中放置任何通常会赋予不同外观而不是位置的美学(除了一些例外,如 xylabel),那么这会启动创造一个传奇。您可以映射 数据集中的一列(如上), 您可以只提供一个值,该值将应用于整个用于 geom 的数据集。在这种情况下,当您将每个 geom 调用的 fill= 参数更改为 aes() 内并将其分配给一个字符值时,看看会发生什么:

p1 <- ggplot(mapping = aes(x=my_x, y=my_y)) +
  stat_summary_bin(aes(fill="first"), data=df1, fun="mean", geom="bar", bins=40, alpha=0.3) +
  stat_summary_bin(aes(fill="second"), data=df2, fun="mean", geom="bar", bins=40, alpha=0.3) +
  scale_fill_manual(values = c("first" = "blue", "second" = "red"))
p1

有效!当您为 aes() 内的 fill= 审美提供一个字符值时,它基本上是将该数据中的每个观察标记为具有值 "first""second" 并使用它来制作传奇。很酷吧?

您注意到一个问题,即图例的 alpha 值不正确。这是因为你 overplotting。这只是您不应该真正这样做的原因之一,但是……有点管用。仅当您具有 alpha 值时才会注意到。你可以让它看起来很正常,但你需要使用 guide_legend() 来覆盖美学。由于代码有效地导致为每个几何体完全绘制图例...您必须将 alpha 值减半才能正确显示。

p1 + guides(fill=guide_legend(override.aes = list(alpha=0.15)))

哦,不使用方法 2 的真正原因是......想想对 5 个数据集再做一次......10 个怎么样?......20 个怎么样?......