为了使异常点的颜色与您的箱线图相同,您需要单独计算异常值并绘制它们。据我所知,内置选项将所有异常值都涂上相同的颜色。
帮助文件示例
使用与“geom_boxplot”帮助文件相同的数据:
ggplot(mtcars, aes(x=factor(cyl), y=mpg, col=factor(cyl))) +
geom_boxplot()
![帮助文件演示](https://istack.dev59.com/vS7Yu.webp)
着色异常点
现在可能有更简单的方法来完成这个任务,但我喜欢手动计算,这样我就不必猜测底层发生了什么。使用'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)))
![离群点的颜色](https://istack.dev59.com/T86Uv.webp)
代码中我们所做的是确定一个空的“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'数据框上执行该语句,因此我们添加它。
我们希望对'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)]
仅为对比,如果我们使用'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)