为了使异常点的颜色与箱线图相同,您需要计算异常值并分别绘制它们。据我所知,为异常值着色的内置选项将所有异常值都涂成相同的颜色。
帮助文件示例
使用与“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