Ggplot,最后一个 Geom_point 着色覆盖了第一个着色 OP 示例中真正发生了什么如何修复使用带填充颜色的点形状覆盖颜色图例的美感

问题描述

如何使点的着色变得具体?正如下面的代码所示,我使用最后一种颜色覆盖了第一种颜色,现在在我的图例中,我的 data1 和 data2 具有相同的颜色,这不是我想要的。

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json","description": "","datasets": {
    "data": [
      {"x": 0,"y": 100,"size": 1},{"x": 50,"y": 0,"size": 1}
    ]
  },"layer": [
    {
      "data": {"name": "data"},"mark": {"type": "point","filled": true,"color": "#a7f3d0"},"encoding": {
        "size": {"field": "size","type": "ordinal","legend": null},"x": {
          "field": "x","title": "","scale": {"domain": [0,10,50,100]}
        },"y": {
          "field": "y","scale": {"domain": [100,0]}
        }
      }
    },{
      "data": {"name": "data"},"shape": "diamond"},"encoding": {
        "x": {"field": "x","aggregate": "mean","title": ""},"y": {"field": "y","title": ""}
      }
    }
  ]}

只是强调 data1 和 data2 是在特定条件下由数据导出的

解决方法

首先,让我们谈谈您的示例中真正发生了什么。那么,我将提供两种解决方法。

OP 示例中真正发生了什么

这是 OP 示例的代表:

library(ggplot2)

set.seed(8675309)
data1 <- data.frame(x=1:10,y=rnorm(10,10))
data2 <- data.frame(x=sample(1:10,10,replace=TRUE),11,0.4))

ggplot(mapping= aes(x=x,y=y)) +
  geom_point(data=data1,aes(fill='data1'),shape='*',size=12,color='blue') +
  geom_point(data=data2,aes(fill='data2'),color='red')

enter image description here

乍一看,看起来这些点的颜色与我们希望的一样,但图例仅由最后一个 geom_point 着色。 但是...这实际上并不是这里发生的事情。实际上,图例中的结果是由于在两个图例键中在蓝点之上 绘制了一个红点。当您更改蓝点的形状时,我们可以非常清楚地证明这一点:

ggplot(mapping= aes(x=x,color='red')

enter image description here

过度绘图的原因很简单:OP 在 fill 中设置了 aes() 美学,然后离散调整了 color 修饰符。因此,图例反映的不是color 的差异,而是fill 的差异。由于“*”不是具有fill的形状,因此除了color的不同外,外观没有任何不同。

如何修复

有两种方法可以解决这个问题。两者都涉及将 coloroutside aes() 移动到 inside aes()。一种方法将两个数据集 data1data2 维护为单独的数据框,就像 OP 一样,我们对每个数据集都有一个 geom_point 调用,第二种方法适用于 Tidy Data原则,并且通常是更好的做法,用于使用 ggplot2 进行绘图。

不整洁的方式

color 移动到 aes() 内以进行 geom_point 调用并删除 fill,因为它在此处不适用。这样做的结果将意味着 ggplot 将创建一个图例并向该图例添加“data1”和“data2”。颜色是自动选择的,但是如果我们想指定颜色,我们可以使用scale_color_manual()

ggplot(mapping= aes(x=x,aes(color='data1'),size=12) +
  geom_point(data=data2,aes(color='data2'),size=12) +
  scale_color_manual(values=c('blue','red'))

enter image description here

顺便说一下,如果您将 color 保持在 内,aes() 外,则 coloraes() outside } 将覆盖 aes() 函数内的那个。这意味着您的点将是正确的颜色,但不会绘制图例。

整洁的数据方式

同样,这种方式更受欢迎。这个想法是你应该将你的数据集合并成一个,添加一列来区分数据的来源。然后,您可以使用该列来指示如何标记点和为点着色。您只需调用一次 geom_point 即可完成这项工作。在此特定示例中,它可能看起来没有太大改进,但请考虑一下如果您有 10 个数据集会有什么不同。

library(dplyr)
library(tidyr)

# note we add a named list to ensure the id column is correctly populated
df <- bind_rows(list(data1=data1,data2=data2),.id="id")

ggplot(df,aes(x=x,y=y,color=id)) + geom_point(shape='*','red'))

结果图与另一个相同。

编辑:如果已经有了色彩美感怎么办?

虽然不是问题的一部分,但 OP 表示,在他们的特定情况下,已经定义了 color 美学(因此发送给 scale_color_manual() 的值是不够的。有一些选项用于如何在此处进行:

  • 在 OP 的情况下,消息表明他们需要提供 6 个值,而不是 2 个值。 OP 可以尝试提供 6 种颜色并使用命名向量(即 c("data1" = "blue","data2" = "red",...)相应地映射它们。
  • 使用具有填充颜色的点形状并将其用于单独的图例
  • 使用相同的星号 * 点形状和颜色,但覆盖图例中的美感。

如果没有来自 OP 的实际数据以及他们专门使用的包含相互冲突的色彩美学的代码,则很难为该特定情况建议最佳课程;不过,我将在这里演示最后两种方法:

使用带填充颜色的点形状

ggplot(mapping= aes(x=x,shape=21,color='NA') +
  geom_point(data=data2,color='NA') +
  scale_fill_manual(values=c('data1'='blue','data2'='red'))

enter image description here

覆盖颜色图例的美感

ggplot(mapping= aes(x=x,color='red') +
  guides(
    fill=guide_legend(override.aes = list(color=c('blue','red')))
  )

enter image description here