68

我在 ggplot2 中绘制了一个密集的散点图,其中每个点都可能用不同的颜色标记:

df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x
df$label <- c("a")
df$label[50] <- "point"
df$size <- 2

ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size))

当我这样做时,标记为“点”(绿色)的散点被绘制在标记为“a”的红点之上。是什么控制了 ggplot 中的 z 顺序,即什么控制了哪个点在哪个点之上?

例如,如果我希望所有“a”点都位于所有标记为“point”的点之上(这意味着它们有时会部分或完全隐藏该点)?这是否取决于标签的字母数字顺序?

我想找到一个可以轻松转换为 rpy2 的解决方案。

4

4 回答 4

59

2016 年更新:

订单美学已被弃用,因此此时最简单的方法是对 data.frame 进行排序,使绿点位于底部,最后绘制。如果您不想更改原始 data.frame,您可以在 ggplot 调用期间对其进行排序 - 这是一个使用%>%arrange来自 dplyr 包进行动态排序的示例:

library(dplyr)
ggplot(df %>%
         arrange(label),
       aes(x = x, y = y, color = label, size = size)) +
  geom_point()

在此处输入图像描述

ggplot2 版本 < 2.0.0 的 2015 年原始答案

在 ggplot2 中,您可以使用order 美学来指定绘制点的顺序。最后绘制的将出现在顶部。要应用这一点,您可以创建一个变量来保存您希望绘制点的顺序。

通过将绿点绘制在其他点之后将其放在顶部:

df$order <- ifelse(df$label=="a", 1, 2)
ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size, order=order))

或者先绘制绿点并将其掩埋,以相反的顺序绘制点:

ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size, order=-order))

对于这个简单的示例,您可以跳过创建新的排序变量,只需将label变量强制转换为一个因子,然后是一个数字:

ggplot(df) +
  geom_point(aes(x=x, y=y, color=label, size=size, order=as.numeric(factor(df$label))))
于 2015-03-29T03:36:46.067 回答
59

ggplot2将逐层创建绘图,并且在每一层内,绘图顺序由geom类型定义。默认是按照它们出现在data.

有不同之处,请注明。例如

geom_line

连接观察值,按 x 值排序。

geom_path

按数据顺序连接观察结果


也有关于排序的已知问题,factors有趣的是注意到包作者 Hadley 的回应

绘图的显示应该与数据框的顺序保持不变 - 其他任何东西都是错误。


记住这句话,图层是按指定的顺序绘制的,因此过度绘图可能是一个问题,尤其是在创建密集散点图时。因此,如果您想要一个一致的图(而不是依赖于数据框中的顺序的图),您需要多考虑一下。


创建第二层

如果您希望某些值出现在其他值之上,您可以使用该subset参数创建第二个图层,以便之后确定绘制。您将需要显式加载plyr包以便.()工作。

set.seed(1234)
df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x
df$label <- c("a")
df$label[50] <- "point"
df$size <- 2
library(plyr)
ggplot(df) + geom_point(aes(x = x, y = y, color = label, size = size)) +
  geom_point(aes(x = x, y = y, color = label, size = size), 
             subset = .(label == 'point'))

在此处输入图像描述

更新

ggplot2_2.0.0中,该subset参数已被弃用。使用 egbase::subset选择data参数中指定的相关数据。并且无需加载plyr

ggplot(df) +
  geom_point(aes(x = x, y = y, color = label,  size = size)) +
  geom_point(data = subset(df, label == 'point'),
             aes(x = x, y = y, color = label, size = size))

或使用alpha

避免过度绘制问题的另一种方法是设置alpha点的(透明度)。这不会像上面明确的第二层方法那样有效,但是,通过明智地使用scale_alpha_manual你应该能够得到一些工作。

例如

# set alpha = 1 (no transparency) for your point(s) of interest
# and a low value otherwise
ggplot(df) + geom_point(aes(x=x, y=y, color=label, size=size,alpha = label)) + 
  scale_alpha_manual(guide='none', values = list(a = 0.2, point = 1))

在此处输入图像描述

于 2013-04-02T22:42:35.623 回答
23

这里的基本问题可以改写如下:

如何控制情节的层次?

在“ggplot2”包中,您可以通过将每个不同的层拆分为不同的命令来快速完成此操作。考虑层次需要一些练习,但它本质上归结为你想要在其他事物之上绘制的内容。您从背景向上构建。

Prep:准备样本数据。此步骤仅在此示例中是必需的,因为我们没有要处理的真实数据。

# Establish random seed to make data reproducible.
set.seed(1)

# Generate sample data.
df <- data.frame(x=rnorm(500))
df$y = rnorm(500)*0.1 + df$x

# Initialize 'label' and 'size' default values.
df$label <- "a"
df$size <- 2

# Label and size our "special" point.
df$label[50] <- "point"
df$size[50] <- 4

您可能会注意到,我在示例中添加了不同的大小,只是为了使图层差异更加清晰。

第 1 步:将数据分层。在使用“ggplot”功能之前,请务必执行此操作。太多人因为试图使用“ggplot”函数进行数据操作而陷入困境。在这里,我们要创建两层:一层带有“a”标签,一层带有“点”标签。

df_layer_1 <- df[df$label=="a",]
df_layer_2 <- df[df$label=="point",]

您可以使用其他函数来执行此操作,但我只是快速使用数据框匹配逻辑来提取数据。

第 2 步:将数据绘制为图层。我们想先绘制所有“a”数据,然后绘制所有“点”数据。

ggplot() + 
    geom_point(
        data=df_layer_1,
        aes(x=x, y=y), 
        colour="orange", 
        size=df_layer_1$size) +
    geom_point(
        data=df_layer_2, 
        aes(x=x, y=y), 
        colour="blue", 
        size=df_layer_2$size)

演示图

请注意,基本绘图层ggplot()没有分配数据。这很重要,因为我们将覆盖每一层的数据。然后,我们有两个单独的点几何层geom_point(...),它们使用自己的规范。x 和 y 轴将共享,但我们将使用不同的数据、颜色和大小。

将颜色和尺寸规格移到aes(...)函数之外很重要,因此我们可以按字面意思指定这些值。否则,“ggplot”函数通常会根据数据中的级别分配颜色和大小。例如,如果数据中的大小值为 2 和 5,它将为任何出现的值 2 分配默认大小,并为任何出现的值 5 分配更大的大小。 “aes”函数规范将不要使用值 2 和 5 作为尺寸。 颜色也是如此。我有想要使用的确切尺寸和颜色,所以我将这些参数移到“geom_plot”函数本身。此外,“aes”功能中的任何规范都会放入图例中,这真的没用。

最后说明:在本例中,您可以通过多种方式获得想要的结果,但重要的是要了解“ggplot2”图层的工作原理,以便充分利用“ggplot”图表。只要在调用“ggplot”函数之前将数据分成不同的层,您就可以很好地控制屏幕上的图形绘制方式。

于 2013-04-04T16:10:45.370 回答
10

它按 data.frame 中的行顺序绘制。尝试这个:

df2 <- rbind(df[-50,],df[50,])
ggplot(df2) + geom_point(aes(x=x, y=y, color=label, size=size))

如您所见,绿点是最后绘制的,因为它代表 data.frame 的最后一行。

这是一种命令 data.frame 先绘制绿点的方法:

df2 <- df[order(-as.numeric(factor(df$label))),]
于 2013-03-29T15:38:25.563 回答