2013-03-07 62 views
11

如何为ggplot2中的异常点着色?我希望它们和盒子本身的颜色一样。 colour=是不够的做到这一点。着色盒在ggplot2中绘制离群值点?

实施例:

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

你可以发布一个代码示例,为人们从工作?这将鼓励更多有用的答案。 – Dinre 2013-03-07 14:03:27

+0

@Dinre:好点,添加示例 – user248237dfsf 2013-03-07 14:44:48

回答

15

为了上色离群点与您的箱线图,你会需要计算离群值并分别绘制它们。据我所知,用于着色异常值的内置选项使所有异常值都具有相同的颜色。

帮助文件例如

使用相同的数据 'geom_boxplot' 帮助文件:

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

help file demo

着色离群点

现在有可能是更简化的方式来做t他的,但我更喜欢手动计算事情,所以我不必猜测发生了什么。使用“plyr”包,我们可以迅速得到上限和下限为使用默认的用于确定孤立点,其在该范围之外的任何点(图基)方法[Q1 - 1.5 * IQR,Q3 + 1.5 * IQR]。 Q1和Q3是数据的1/4和3/4分位数,IQR = Q3 - Q1。我们可以写这一切作为一个巨大的语句,但由于“plyr”包装的“变异”功能将让我们引用新创建的列,我们不妨起来把它分解为更容易阅读/调试,就像这样:

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”帘布层)。在上述“ddply”语句的“发生变异”功能被保留原始数据帧并添加额外的列,以及.(cyl)说明书告诉为“CYL”值中的每个分组进行计算的功能。

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

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

colored outliers

我们在代码正在做什么是指定一个空“ggplot”层,然后将使用独立的数据箱线图和点的几何形状。 boxplot几何可以使用原始数据框,但我正在使用我们新的'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”函数。这将保留旧数据并将新计算添加为新列。这与“汇总”等其他功能形成了对比,“汇总”功能可删除除分组变量之外的所有旧列。

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

幸运的是,与“发生变异”功能,我们可以使用新创建的列,其他列的定义的一部分。这使我们不必编写一个巨大的函数或不必运行多个函数。我们需要在计算'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 
+1

谢谢你的帮助,但非常复杂......是不是可能只是获取'因素(cyl)'的颜色,并且将一个向量交给'outlier.colour'?即明确告诉ggplot每个异常值应该是什么颜色,而不是计算异常值点? – user248237dfsf 2013-03-07 15:03:38

+2

@ user248237dfsf据我所知,'outlier.colour ='参数不允许使用颜色矢量。你试图在'geom_boxplot'函数的预期行为之外做一些事情,所以它不能在函数内完成。此外,几行代码并不完全是我所说的“非常复杂”。比单个参数更复杂?当然。比写一个新的boxplot函数更复杂吗?不是由一个长镜头。 – Dinre 2013-03-07 15:10:13

+0

复杂的含义,它需要你重复计算通常由boxplot完成的异常值,并且介绍了计算离群值与boxplot等略有不同的可能性等等。在这种情况下,我会选择一种方法来设置颜色每个boxplot手动对象,但如果这是不可能的我想这是唯一的方法 – user248237dfsf 2013-03-07 19:33:00

4

如果有必要根据(其被用于制造箱线图组不相同)不同因子然后@Dinre的答案可以适于改变离群点的形状或颜色。

只有当颜色不用于boxplot本身时,才可以更改点的颜色(不能对颜色使用两个变量)。

使用数据plot_Data和来自@Dinre答案的代码 - 异常值的颜色取决于因子carb。通过添加参数outlier.shape = NAgeom_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))) 

enter image description here

要更改点的形状:

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

enter image description here

+0

谢谢,但我想通过变量条件对它着色。这似乎并不起作用:''p < - ggplot(mtcars,aes(factor(cyl),mpg)) > p + geom_boxplot(aes(outlier.colour = factor(cyl)),outlier.size = 3) ' – user248237dfsf 2013-03-07 14:42:41

+0

当你改变形状时,你是否在geom_boxplot()调用的圆形异常值上绘制了异形异常值?您应该/可以关闭geom_boxplot()调用中的异常值吗? – John 2013-10-28 18:56:09

+1

@John - 您可以用参数outlier.shape = NA删除原始异常值。更新了我的答案。 – 2013-10-28 19:01:35

24

更新(2015年3月31日):参见ggplot2 < = 0.9.3 @tarch's solution for ggplot2 >= 1.0.0

溶液如下。


正如@koshke所述,具有着色像箱(未填充颜色)的线的异常值是现在容易实现通过设置outlier.colour = NULL

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

boxplot with coloured outliers

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

我张贴这是一个迟到的回答,因为我发现自己再次寻找这个再次和我的贴吧也为相关的问题Boxplot, how to match outliers' color to fill aesthetics?

+0

+1谢谢!这是诀窍。不再需要黑客。 – Juve 2013-11-15 16:19:49

+0

这应该是新接受的答案。 +1 – RyanStochastic 2014-01-07 23:27:43

+2

你使用的是什么版本的ggplot2?使用1.0.0这不会产生有色异常值 – Hamy 2014-10-08 03:59:04

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

预期这将产生相匹配的线颜色点的情节。

当然应该记住恢复默认的,如果他需要借助多条曲线:

geom_boxplot()使用异常值:

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

该解决方案由GitHub上读取ggplot2 changelog发现默认颜色,尺寸和形状从 geom_point()。将geom_point()的默认值更改为 update_geom_defaults()将对 geom_boxplot()的异常值应用相同的更改。更改异常值的默认值以前不是 。 (@ThierryO,#757)

在这里发布,以及:ggplot2 boxplot, how do i match the outliers' color to fill aesthetics?

+0

我可以证实这适用于较新版本 - 这应该是最重要的答案。 – slhck 2015-03-31 07:48:21

+0

也适用于我,也用AE拼写'color =“black”'。 – mavam 2015-06-25 08:04:21

+0

适合我!谢谢! – 2015-06-25 12:01:25