控制 ggplot2中点的顺序?

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

当我这样做时,标记为“ point”(绿色)的散点被绘制在标记为“ a”的红色点的顶部。在 ggplot 中是什么控制这个 z 顺序,也就是说,是什么控制哪个点在哪个点的上面?

例如,如果我想要所有的“ a”点位于所有标记为“ point”的点的顶部(意味着它们有时会部分或完全隐藏该点) ,该怎么办?这是否依赖于标签的字母数字排序?

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

69001 次浏览

它是按照 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))),]

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

enter image description here

更新

ggplot2_2.0.0中,不推荐使用 subset参数。使用例如 base::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))

enter image description here

这里的基本问题可以这样表述:

我如何控制我的情节的层次?

在“ 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”标签,另一个带有“ point”标签。

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

您可以使用其他函数来完成这项工作,但是我只是快速地使用数据帧匹配逻辑来提取数据。

步骤2 : 将数据作为图层绘制。我们首先要绘制所有的“ a”数据,然后绘制所有的“ point”数据。

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)

demo chart

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

将颜色和大小规格移到 aes(...)函数之外非常重要,因此我们可以逐字地指定这些值。否则,“ ggplot”函数通常会根据数据中的级别分配颜色和大小。例如,如果数据中的 size 值为2和5,它将为出现值2的任何事件分配默认大小,并为出现值5的任何事件分配更大的大小。颜色也是如此。我有我想要使用的确切的大小和颜色,所以我将这些参数移动到‘ geom _ plot’函数本身。另外,“ aes”函数中的任何规范都将被放入图例中,这可能真的没有用处。

最后注意 : 在这个示例中,您可以通过多种方式实现所需的结果,但是为了充分利用“ ggplot”图表,了解“ ggplot2”图层是如何工作的非常重要。只要在调用“ ggplot”函数之前将数据分隔到不同的层中,就可以在很大程度上控制屏幕上的图形显示方式。

2016年更新:

顺序美学 已经被否决了,因此此时最简单的方法是对 data.frame 进行排序,使绿点位于底部,并在最后绘制。如果你不想改变原始的 data.frame,你可以在 ggplot 调用期间对它进行排序——这里有一个使用 dplyr 包中的 %>%arrange进行动态排序的例子:

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

enter image description here

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

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

把绿点放在上面,在其他点之后画上绿点:

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变量强制为 factor,然后为数值:

ggplot(df) +
geom_point(aes(x=x, y=y, color=label, size=size, order=as.numeric(factor(df$label))))