16

如何为ggplot2中的异常点着色?我希望它们与箱线图本身的颜色相同。colour=这样做是不够的。

例子:

p <- ggplot(mtcars, aes(factor(cyl), mpg))
p + geom_boxplot(aes(colour=factor(cyl)))

我也想为异常值着色factor(cyl)。这不起作用:

> p <- ggplot(mtcars, aes(factor(cyl), mpg))
> p + geom_boxplot(aes(colour=factor(cyl), outlier.colour=factor(cyl)))
4

6 回答 6

28

更新(2015-03-31):请参阅@tarch 的解决方案ggplot2>= 1.0.0

<= 0.9.3 的解决方案ggplot2如下。


正如@koshke 所说,现在可以通过设置轻松地将异常值着色为框线(而不是填充颜色)outlier.colour = NULL

p <- ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl)))
p + geom_boxplot(outlier.colour = NULL)

带有彩色异常值的箱线图

  • outlier.colour必须写“ou”
  • outlier.colour必须在外面aes ()

我将其发布为较晚的答案,因为我发现自己一次又一次地查找此问题,并且我还为相关问题Boxplot,如何匹配异常值的颜色以填充美学?

于 2013-04-16T11:34:19.163 回答
15

为了使异常点的颜色与箱线图相同,您需要计算异常值并分别绘制它们。据我所知,为异常值着色的内置选项将所有异常值都涂成相同的颜色。

帮助文件示例

使用与“geom_boxplot”帮助文件相同的数据:

ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
    geom_boxplot()

帮助文件演示

为异常点着色

现在可能有一种更精简的方法来做到这一点,但我更喜欢手工计算,所以我不必猜测引擎盖下发生了什么。使用 'plyr' 包,我们可以快速获取使用默认 (Tukey) 方法确定异常值的上限和下限,该异常值是 [Q1 - 1.5 * IQR, Q3 + 1.5 * IQR] 范围之外的任何点。Q1 和 Q3 是数据的 1/4 和 3/4 分位数,IQR = Q3 - Q1。我们可以将这一切写成一个巨大的语句,但由于 'plyr' 包的 'mutate' 函数将允许我们引用新创建的列,我们不妨将其拆分以便于阅读/调试,如下所示:

library(plyr)
plot_Data <- ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)

我们使用 'ddply' 函数,因为我们正在输入一个数据帧并想要一个数据帧作为输出(“d->d”ply)。上述 'ddply' 语句中的 'mutate' 函数是保留原始数据框并添加额外的列,并且规范.(cyl)是告诉要为每组 'cyl' 值计算的函数。

此时,我们现在可以绘制箱线图,然后用新的彩色点覆盖异常值。

ggplot() +
    geom_boxplot(data=plot_Data, aes(x=factor(cyl), y=mpg, col=factor(cyl))) + 
    geom_point(data=plot_Data[plot_Data$mpg > plot_Data$upper.limit | plot_Data$mpg < plot_Data$lower.limit,], aes(x=factor(cyl), y=mpg, col=factor(cyl)))

有色异常值

我们在代码中所做的是指定一个空的“ggplot”层,然后使用独立数据添加箱线图和点几何图形。箱线图几何可以使用原始数据框,但我使用我们的新“plot_Data”来保持一致。点几何然后仅绘制异常点,使用我们新的“lower.limit”和“upper.limit”列来确定异常状态。由于我们对“x”和“col”美学参数使用相同的规范,因此箱线图和相应的异常点之间的颜色神奇地匹配。

更新:OP 要求对此代码中使用的“ddply”函数进行更完整的解释。这里是:

'plyr' 系列函数基本上是一种对数据进行子集化并对数据的每个子集执行函数的方法。在这种特殊情况下,我们有以下声明:

ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)

让我们按照语句的编写顺序来分解它。首先,“ddply”功能的选择。我们要计算“mtcars”数据中“cyl”每个值的下限和上限。我们可以编写一个“for”循环或其他语句来计算这些值,但是稍后我们将不得不编写另一个逻辑块来评估异常值状态。相反,我们想使用“ddply”来计算下限和上限,并将这些值添加到每一行。我们选择“ddply”(与“dlply”、“d_ply”等相对),因为我们正在输入一个数据帧并想要一个数据帧作为输出。这给了我们:

ddply(

我们想在“mtcars”数据框上执行语句,所以我们添加了它。

ddply(mtcars, 

现在,我们要使用“cyl”值作为分组变量来执行我们的计算。我们使用 'plyr' 函数.()来引用变量本身而不是变量的值,如下所示:

ddply(mtcars, .(cyl),

下一个参数指定要应用于每个组的函数。我们希望我们的计算将新行添加到旧数据中,因此我们选择了“mutate”函数。这会保留旧数据并将新计算添加为新列。这与“summarize”等其他功能形成对比,后者会删除除分组变量之外的所有旧列。

ddply(mtcars, .(cyl), mutate, 

最后一系列参数是我们要创建的所有新数据列。我们通过指定名称(不带引号)和表达式来定义它们。首先,我们创建“Q1”列。

ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), 

“Q3”列的计算方式类似。

ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), 

幸运的是,通过 'mutate' 函数,我们可以使用新创建的列作为其他列定义的一部分。这使我们不必编写一个巨大的函数或不必运行多个函数。我们需要在计算“IQR”变量的四分位间距时使用“Q1”和“Q3”,而使用“mutate”函数很容易。

ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, 

我们终于到了现在想去的地方。从技术上讲,我们不需要“Q1”、“Q3”和“IQR”列,但它确实使我们的下限和上限方程更易于阅读和调试。我们可以像理论公式一样写出我们的表达式:limits=+/- 1.5 * IQR

ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)

为了便于阅读,去掉中间的列,这是新数据框的样子:

plot_Data[, c(-3:-11)]
#     mpg cyl    Q1    Q3  IQR upper.limit lower.limit
# 1  22.8   4 22.80 30.40 7.60      41.800      11.400
# 2  24.4   4 22.80 30.40 7.60      41.800      11.400
# 3  22.8   4 22.80 30.40 7.60      41.800      11.400
# 4  32.4   4 22.80 30.40 7.60      41.800      11.400
# 5  30.4   4 22.80 30.40 7.60      41.800      11.400
# 6  33.9   4 22.80 30.40 7.60      41.800      11.400
# 7  21.5   4 22.80 30.40 7.60      41.800      11.400
# 8  27.3   4 22.80 30.40 7.60      41.800      11.400
# 9  26.0   4 22.80 30.40 7.60      41.800      11.400
# 10 30.4   4 22.80 30.40 7.60      41.800      11.400
# 11 21.4   4 22.80 30.40 7.60      41.800      11.400
# 12 21.0   6 18.65 21.00 2.35      24.525      15.125
# 13 21.0   6 18.65 21.00 2.35      24.525      15.125
# 14 21.4   6 18.65 21.00 2.35      24.525      15.125
# 15 18.1   6 18.65 21.00 2.35      24.525      15.125
# 16 19.2   6 18.65 21.00 2.35      24.525      15.125
# 17 17.8   6 18.65 21.00 2.35      24.525      15.125
# 18 19.7   6 18.65 21.00 2.35      24.525      15.125
# 19 18.7   8 14.40 16.25 1.85      19.025      11.625
# 20 14.3   8 14.40 16.25 1.85      19.025      11.625
# 21 16.4   8 14.40 16.25 1.85      19.025      11.625
# 22 17.3   8 14.40 16.25 1.85      19.025      11.625
# 23 15.2   8 14.40 16.25 1.85      19.025      11.625
# 24 10.4   8 14.40 16.25 1.85      19.025      11.625
# 25 10.4   8 14.40 16.25 1.85      19.025      11.625
# 26 14.7   8 14.40 16.25 1.85      19.025      11.625
# 27 15.5   8 14.40 16.25 1.85      19.025      11.625
# 28 15.2   8 14.40 16.25 1.85      19.025      11.625
# 29 13.3   8 14.40 16.25 1.85      19.025      11.625
# 30 19.2   8 14.40 16.25 1.85      19.025      11.625
# 31 15.8   8 14.40 16.25 1.85      19.025      11.625
# 32 15.0   8 14.40 16.25 1.85      19.025      11.625

只是为了进行对比,如果我们要使用“summarize”函数执行相同的“ddply”语句,那么我们将得到所有相同的答案,但没有其他数据的列。

ddply(mtcars, .(cyl), summarize, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1, upper.limit=Q3+1.5*IQR, lower.limit=Q1-1.5*IQR)
#   cyl    Q1    Q3  IQR upper.limit lower.limit
# 1   4 22.80 30.40 7.60      41.800      11.400
# 2   6 18.65 21.00 2.35      24.525      15.125
# 3   8 14.40 16.25 1.85      19.025      11.625
于 2013-03-07T14:56:58.077 回答
15

我找到了一个解决方案,即设置geom_boxplot(outlier.colour = NULL)在最新版本的 R 中不再起作用(@hamy 谈到 ggplot2 的 1.0.0 版)。

为了复制@cbeleites 提出的行为,您只需使用以下代码:

update_geom_defaults("point", list(colour = NULL))
m <- ggplot(movies, aes(y = votes, x = factor(round(rating)),
            colour = factor(Animation)))
m + geom_boxplot() + scale_y_log10()

正如预期的那样,这会产生与线条颜色匹配的点。

当然,如果他需要绘制多个图,应该记住恢复默认值:

update_geom_defaults("point", list(colour = "black"))

通过阅读github 上的ggplot2 更改日志找到了解决方案:

异常值geom_boxplot()使用来自 的默认颜色、大小和形状 geom_point()geom_point()更改with 的默认值update_geom_defaults()将对 的异常值应用相同的更改 geom_boxplot()。以前无法更改异常值的默认值。(@蒂埃里奥,#757)

也在这里发布:ggplot2 boxplot,我如何匹配异常值的颜色来填充美学?

于 2015-03-13T08:55:29.917 回答
7

如果需要根据不同的因素(与用于制作箱线图组的因素不同)改变异常点的形状或颜色,则可以调整@Dinre 的答案。

仅当颜色本身不用于箱线图时才能更改点的颜色(您不能将两个变量用于颜色)。

使用来自@Dinre 答案的数据plot_Data和代码 - 异常值的颜色取决于因素carboutlier.shape = NA通过向原始异常值添加参数,geom_boxplot()以确保它们不会被geom_point().

ggplot() +
  geom_boxplot(data=plot_Data, aes(x=factor(cyl), y=mpg),outlier.shape = NA) + 
  geom_point(data=plot_Data[plot_Data$mpg > plot_Data$upper.limit | 
                              plot_Data$mpg < plot_Data$lower.limit,], 
             aes(x=factor(cyl), y=mpg, color=factor(carb)))

在此处输入图像描述

要更改点的形状:

ggplot() +
  geom_boxplot(data=plot_Data, aes(x=factor(cyl), y=mpg),outlier.shape = NA) + 
  geom_point(data=plot_Data[plot_Data$mpg > plot_Data$upper.limit | 
                              plot_Data$mpg < plot_Data$lower.limit,], 
             aes(x=factor(cyl), y=mpg, shape=factor(carb)))

在此处输入图像描述

于 2013-03-07T14:03:44.017 回答
3

异常值会自动从 ggplot2 * 1.0.1.9003 中的框中再次继承颜色。

https://github.com/hadley/ggplot2/issues/1400

```{r}
library(ggplot2)
point_size=10
ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
geom_boxplot(outlier.size = point_size)
```

箱形图

于 2015-11-09T23:22:23.837 回答
1

以防万一你真的想让盒子保持黑色:

另一种可能的解决方案是

  1. 将点是否为异常值存储在变量中,
  2. outlier.color = NA用和抑制异常值绘图
  3. 仅绘制那些异常值并col在此调用中使用美学geom_point()

第 1 步:定义一个函数来确定一个点是否为异常值:

is.outlier <- function (x) {
  x < quantile(x, .25) - 1.5 * IQR(x) |
    x > quantile(x, .75) + 1.5 * IQR(x)
}

第 2 步:对数据进行分组并使用此函数为组计算异常值

diamonds %>% group_by(cut) %>%
  mutate(outlier.p = is.outlier(price)) %>%
  ungroup() -> diamonds

第 3 步:创建绘图

ggplot(diamonds, aes(x = cut, y = price, fill = cut)) +
  geom_boxplot(outlier.color = NA) +
  geom_point(data = diamonds[diamonds$outlier.p,], aes(col = cut))

请注意,您必须在geom_point()调用(最后一行)中对数据集进行子集化,以免绘制所有点。

阴谋

于 2019-02-06T15:54:36.720 回答