如何在ggplot2中为异常点着色?我希望它们与boxplot本身颜色相同。 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)))
答案 0 :(得分:24)
更新(2015-03-31):见@tarch's solution for ggplot2
>= 1.0.0
ggplot2
&lt; = 0.9.3的解决方案如下。
正如@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, how to match outliers' color to fill aesthetics?
答案 1 :(得分:15)
为了使离群点的颜色与箱图相同,您需要计算异常值并分别绘制它们。据我所知,用于着色异常值的内置选项将所有异常值都颜色相同。
帮助文件示例
使用与&#39; geom_boxplot&#39;相同的数据帮助文件:
ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
geom_boxplot()
着色离群点
现在可能有一种更简化的方法来做到这一点,但我更喜欢手工计算,所以我不必猜测引擎盖下发生的事情。使用&#39; plyr&#39;包,我们可以快速获得使用默认(Tukey)方法确定异常值的上限和下限,这是超出范围[Q1 - 1.5 * IQR,Q3 + 1.5 * IQR]的任何点。 Q1和Q3是数据的1/4和3/4分位数,IQR = Q3-Q1。我们可以把这一切都写成一个巨大的陈述,但是因为&#39; plyr&#39;包装变种&#39;函数将允许我们引用新创建的列,我们不妨将其拆分以便于读取/调试,如下所示:
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)
我们使用&#39; ddply&#39;函数,因为我们输入数据帧并希望数据帧作为输出(&#34; d-&gt; d&#34; ply)。 &#39;变异&#39;功能在上面&#39; ddply&#39;声明保留原始数据框并添加其他列,.(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)))
我们在代码中所做的是指定一个空的&#39; ggplot&#39;图层,然后使用独立数据添加boxplot和点几何。 boxplot几何可以使用原始数据框,但我正在使用我们新的&#39; plot_Data&#39;要保持一致。然后,点几何图形仅绘制异常点,使用我们新的&quot; lower.limit&#39;和&#39; upper.limit&#39;用于确定异常状态的列。因为我们对&#39; x&#39;使用相同的规范。和&#39; col&#39;美学论证,颜色在箱形图和相应的异常点之间神奇地匹配。
更新:OP要求对“ddply”进行更全面的解释。此代码中使用的函数。这是:
&#39; plyr&#39;函数族基本上是一种对数据进行子集化并对每个数据子集执行函数的方法。在这种特殊情况下,我们有声明:
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)
让我们按照语句写的顺序将其分解。首先,选择&#39; ddply&#39;功能。我们想要计算每个值的下限和上限。在&#39; mtcars&#39;数据。我们可以写一个&#39; for&#39;循环或其他语句来计算这些值,但之后我们将不得不再写一个逻辑块来评估异常值状态。相反,我们想要使用&#39; ddply&#39;计算下限和上限并将这些值添加到每一行。我们选择&#39; ddply&#39; (与'dlply&#39;,&#39; d_ply&#39;等)相反,因为我们正在输入数据帧并希望将数据帧作为输出。这给了我们:
ddply(
我们希望在&#39; mtcars&#39;上执行声明。数据框,所以我们添加。
ddply(mtcars,
现在,我们想要使用&#39; cyl&#39;来执行我们的计算。值作为分组变量。我们使用&#39; plyr&#39;函数.()
引用变量本身而不是变量的值,如下所示:
ddply(mtcars, .(cyl),
下一个参数指定要应用于每个组的函数。我们希望我们的计算为旧数据添加新行,因此我们选择“变异”#39;功能。这将保留旧数据并将新计算添加为新列。这与其他函数形成对比,例如&#39; summary&#39 ;,删除除分组变量之外的所有旧列。
ddply(mtcars, .(cyl), mutate,
最后一系列参数是我们想要创建的所有新数据列。我们通过指定名称(未引用的)和表达式来定义它们。首先,我们创建了&#39; Q1&#39;列。
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4),
&#39; Q3&#39;列的计算方法类似。
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4),
幸运的是,随着变异&#39;函数,我们可以使用新创建的列作为其他列定义的一部分。这使我们不必编写一个巨大的函数或必须运行多个函数。我们需要使用&#39; Q1&#39;和&#39; Q3&#39;在计算IQR&#39;的四分位数范围时变量,并且“变异”变得容易。功能
ddply(mtcars, .(cyl), mutate, Q1=quantile(mpg, 1/4), Q3=quantile(mpg, 3/4), IQR=Q3-Q1,
我们终于想到了现在的位置。从技术上讲,我们不需要第一季度,第三季度和第三季度的IQR&#39;列,但它确实使我们的下限和上限方程更容易阅读和调试。我们可以像理论公式一样编写表达式: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
只是为了给对比,如果我们要做同样的事情&#39; ddply&#39;声明&#39;总结&#39;相反,我们会得到所有相同的答案,但没有其他数据的列。
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
答案 2 :(得分: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 changelog找到解决方案:
geom_boxplot()
的异常值使用默认颜色,大小和形状geom_point()
。使用更改geom_point()
的默认值update_geom_defaults()
会将相同的更改应用于异常值geom_boxplot()
。之前没有更改异常值的默认值 可能。 (@ThierryO,#757)
也在此发布:ggplot2 boxplot, how do i match the outliers' color to fill aesthetics?
答案 3 :(得分:6)
如果需要根据不同的因素(用于制作箱线图组的不同因素)改变异常点的形状或颜色,则可以调整@Dinre的答案。
只有当颜色不用于箱图本身时才能改变点的颜色(你不能将两个变量用于颜色)。
使用数据plot_Data
和@Dinre答案中的代码 - 异常值的颜色取决于因子carb
。通过向outlier.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)))
答案 4 :(得分: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)
```
答案 5 :(得分:0)
以防万一,您真的想将盒子保持黑色:
另一种可能的解决方案是
outlier.color = NA
抑制异常值绘制,并且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()
调用(最后一行)中对数据集进行子集化,以免绘制所有点。