忽略ggplot2 boxplot中的异常值


132

我如何忽略ggplot2 boxplot中的离群值?我不只是希望它们消失(即outlier.size = 0),而是希望它们被忽略,以便y轴缩放以显示第一/第三百分位数。我的异常值导致“盒子”缩小到几乎只有一条线。有一些技巧可以解决这个问题吗?

编辑 这是一个例子:

y = c(.01, .02, .03, .04, .05, .06, .07, .08, .09, .5, -.6)
qplot(1, y, geom="boxplot")

在此处输入图片说明


一些示例数据和可重现的示例将使您更轻松地获得帮助。
Andrie

3
我的档案是200兆!只需选取第1个和第3个分位数之间有许多数据点以及一些离群值(您只需要1个)的任何数据集即可。如果离群值离第一/第三远,那么框
肯定

是的,这就是我的想法。组成这样的数据集,并使用dput()将其与您使用的ggplot()语句一起发布到此处。帮助我们来帮助您。
Andrie

您是否可以仅更改y轴限制以“放大”您感兴趣的y轴部分?
加文·辛普森

2
让我看看...。哦,对不起。只需fivenum()对数据进行处理,以提取用于scale_y_continuous()框线图上下铰链的IIRC,然后在@Ritchie显示的调用中使用该输出。使用R和ggplot提供的工具,可以非常轻松地实现自动化。如果还需要包含晶须,请考虑使用boxplot.stats()来获取晶须的上限和下限,然后在中使用scale_y_continuous()
加文·辛普森

Answers:


140

这是使用boxplot.stats的解决方案

# create a dummy data frame with outliers
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))


# compute lower and upper whiskers
ylim1 = boxplot.stats(df$y)$stats[c(1, 5)]

# scale y limits based on ylim1
p1 = p0 + coord_cartesian(ylim = ylim1*1.05)

15
+1用于自动计算,+ 1用于使用coord_cartesian缩放而不是排除数据
Ben Bolker

2
@Ben-您有两个帐户?=)@Ramnath-这是一个非常优雅的解决方案
SFun28

7
使用上述方法,限制可能会因一侧的小极限值和另一侧的大极限值而产生偏差,例如ylim <- c(-0.1, 1000) * 1.05给定[1] 0.105 1050。要在均值附近获得相等的限制,可以使用ylim + c(-0.05, 0.05) * diff(ylim) / 2。我认为更漂亮。
Bram Visser

2
@Ramnath $ stats [c(1,5)]会做什么?
lukeg

3
如果使用,则该键不起作用facet_grid()。然后,您将获得多个框线图,而不是一个。因此,您没有得到正确的限制。
WitheShadow

204

使用geom_boxplot(outlier.shape = NA)不显示异常值和scale_y_continuous(limits = c(lower, upper))改变轴界限。

一个例子。

n <- 1e4L
dfr <- data.frame(
  y = exp(rlnorm(n)),  #really right-skewed variable
  f = gl(2, n / 2)
)

p <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot()
p   # big outlier causes quartiles to look too slim

p2 <- ggplot(dfr, aes(f, y)) + 
  geom_boxplot(outlier.shape = NA) +
  scale_y_continuous(limits = quantile(dfr$y, c(0.1, 0.9)))
p2  # no outliers plotted, range shifted

实际上,正如Ramnath在他的回答中所显示的那样(Andrie在评论中也是如此),在通过计算统计信息之后裁切比例尺更为有意义coord_cartesian

coord_cartesian(ylim = quantile(dfr$y, c(0.1, 0.9)))

(您可能仍需要使用它scale_y_continuous来修复轴断裂。)


1
因此,我将不得不计算下限/上限-也许是通过计算第一/第三百分位数?意味着没有自动魔术方法告诉gg-plot2忽略异常值并进行智能扩展吗?
SFun28年

38
注意scale_y_continuous(limits = ...),这将删除超出限制的数据,然后执行统计计算。换句话说,均值和其他摘要将受到影响。如果这是您想要的,那就太好了。另一种方法是使用coord_cartesian(limits = ...)-在不删除数据或不影响摘要的情况下进行“缩放”。
Andrie

@Andrie-谢谢!我不希望卑鄙和其他摘要受到影响。
SFun28 2011年

1
coord_cartesian()coord_flip()根据我的经验,它不能很好地配合使用,所以我更喜欢scale_y_continuous()
PatrickT

1
这是最好的解决方案。我想隐藏异常值的原因是因为我还使用geom_jitter绘制了抖动点。在这种情况下,离群值会妨碍您,使它看起来像有很多点超出了应有的数量。
williamsurles

14

我有同样的问题,并使用以下方法预先计算了Q1,Q2,中位数,ymin,ymax的值boxplot.stats

# Load package and generate data
library(ggplot2)
data <- rnorm(100)

# Compute boxplot statistics
stats <- boxplot.stats(data)$stats
df <- data.frame(x="label1", ymin=stats[1], lower=stats[2], middle=stats[3], 
                 upper=stats[4], ymax=stats[5])

# Create plot
p <- ggplot(df, aes(x=x, lower=lower, upper=upper, middle=middle, ymin=ymin, 
                    ymax=ymax)) + 
    geom_boxplot(stat="identity")
p

结果是没有异常值的箱线图。 在此处输入图片说明


9

一种想法是通过两个过程对数据进行解冻

  1. 进行第一遍,了解边界是什么,例如,在给定百分位数处进行切割,或在均值之上的N个标准偏差,或...

  2. 在第二遍中,将超出给定界限的值设置为该界限的值

我应该强调,这是一种老式的方法,应该由更现代的鲁棒技术主导,但是您仍然会遇到很多。


1
谁只是默默地投票反对:发表评论以解释原因
Dirk Eddelbuettel 2011年

不是我 只是想补充一下,在环境数据中,将晶须停在百分位数(通常为第10位和第90位)上似乎很常见。
Richie Cotton

我是一个沉默的+1,希望我能再提供一个。Winsorizing几乎总是在经济+金融中完成。如果SFun的异常值破坏了数据的可视化,我想知道它们对数据分析的影响是什么。
理查德·赫伦

在重新阅读这篇文章时,您提到风化是一种较旧的技术....还有什么更现代的技术?
SFun28年

1
通常,随着过去30多年的发展,健壮的方法。
2011年

2

geom_boxplot函数的“ coef”选项允许根据四分位间距更改离群截止值。该选项记录在stat_boxplot函数中。要停用异常值(换句话说,它们被视为常规数据),可以代替默认值1.5来指定非常高的截止值:

library(ggplot2)
# generate data with outliers:
df = data.frame(x=1, y = c(-10, rnorm(100), 10)) 
# generate plot with increased cutoff for outliers:
ggplot(df, aes(x, y)) + geom_boxplot(coef=1e30)

3
它只是扩大了胡须,它并没有改变图表的任何
比例

2

如果要强制晶须扩展到最大值和最小值,则可以调整coef参数。默认值为coef1.5(即,晶须的默认长度为IQR的1.5倍)。

# Load package and create a dummy data frame with outliers 
#(using example from Ramnath's answer above)
library(ggplot2)
df = data.frame(y = c(-100, rnorm(100), 100))

# create boxplot that includes outliers
p0 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)))

# create boxplot where whiskers extend to max and min values
p1 = ggplot(df, aes(y = y)) + geom_boxplot(aes(x = factor(1)), coef = 500)

p0的图像

p1的图片


2

Ipaper :: geom_boxplot2就是您想要的。

# devtools::install_github('kongdd/Ipaper')
library(Ipaper)
library(ggplot2)
p <- ggplot(mpg, aes(class, hwy))
p + geom_boxplot2(width = 0.8, width.errorbar = 0.5)

在此处输入图片说明


谢谢!!经过我的数据测试,完美无缺!尽管我不确定github的稳定性/长期支持,我还是会推荐这种解决方案。
吉尔达斯(Gildas)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.