我将如何忽略 ggplot2 boxplot 中的异常值?我不只是希望它们消失(即 outlier.size=0),而是希望它们被忽略,以便 y 轴缩放以显示第 1/3 个百分位数。我的异常值导致“盒子”缩小到几乎是一条线。有一些技术可以解决这个问题吗?
编辑这是一个例子:
y = c(.01, .02, .03, .04, .05, .06, .07, .08, .09, .5, -.6)
qplot(1, y, geom="boxplot")
https://i.stack.imgur.com/mb3In.png
fivenum()
以提取 IIRC 用于箱线图上铰链和下铰链的内容,并在 @Ritchie 显示的 scale_y_continuous()
调用中使用该输出。这可以使用 R 和 ggplot 提供的工具非常容易地自动化。如果您还需要包括胡须,请考虑使用 boxplot.stats()
来获取胡须的上限和下限,然后在 scale_y_continuous()
中使用。
使用 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
来修复轴中断。)
这是使用 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)
ylim <- c(-0.1, 1000) * 1.05
给出 [1] 0.105 1050
。要在平均值附近获得相等的限制,您可以使用 ylim + c(-0.05, 0.05) * diff(ylim) / 2
。在我看来更漂亮。
facet_grid()
,则它不起作用。然后你有多个箱线图而不是一个。因此,您没有得到正确的限制。
我遇到了同样的问题,并使用 boxplot.stats
预先计算了 Q1、Q2、中位数、ymin、ymax 的值:
# 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
https://i.stack.imgur.com/vQwX4.png
一种想法是在两遍过程中winsorize数据:
运行第一遍,了解界限是什么,例如在给定百分位数处的截断,或高于平均值的 N 个标准差,或者......在第二遍中,将超出给定界限的值设置为该界限的值
我要强调的是,这是一种老式的方法,应该由更现代的强大技术主导,但你仍然经常遇到它。
gg.layers::geom_boxplot2
正是您想要的。
# remotes::install_github('rpkgs/gg.layers')
library(gg.layers)
library(ggplot2)
p <- ggplot(mpg, aes(class, hwy))
p + geom_boxplot2(width = 0.8, width.errorbar = 0.5)
https://i.stack.imgur.com/ZQpAV.png
如果您想强制胡须扩展到最大值和最小值,您可以调整 coef
参数。 coef
的默认值为 1.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)
https://i.stack.imgur.com/PTCJp.png
https://i.stack.imgur.com/pjgdb.png
简单、肮脏和有效。 geom_boxplot(outlier.alpha = 0)
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)
coord_cartesian()
不能很好地与coord_flip()
配合使用,因此我更喜欢scale_y_continuous()
。