为多个变量显示异常值标签 ggplot 和 geom_boxplot r?

Show outlier labels ggplot and geom_boxplot r for multiple variables?

有什么解决问题的建议吗? 与频道上将变量的解决方案作为一个因素呈现的其他类似问题不同,我的情况有所不同。我想查看多个变量的异常值标签。

我有如下图表。 例如:

它是用这个命令创建的:

z_mtcars <-data.frame(scale(mtcars[-12]))
z_mtcars$type<-rownames(mtcars)
z_mtcars %>% melt(id.vars = "type")  %>%
ggplot() +
aes( x = variable, y = value, fill = as.numeric(variable)) +
geom_boxplot() +
scale_fill_distiller(palette = "Blues") +
scale_alpha(range = c(1,1)) +
ggtitle("Boxplot: Standardized Score (Z-Scale) ") +
xlab("Variables") +
ylab("Value") + 
labs(fill = "Order of \nVariables") +
theme_classic() +
theme(axis.text.x = element_text(angle = 90,hjust = 1)) +
geom_hline(yintercept = 0, linetype = "dashed", color = "red") +
geom_hline(yintercept = 1, linetype = "dotted", color = "blue") +
theme(legend.position = "left")

这是我试过的。我稍微简化了您的代码以突出您要问的要点。你想以某种方式找到异常值的标签信息。您可以使用下面借用的函数来识别异常值。当您识别它们时,您将汽车名称添加到一个名为离群值的新列中。您在 ggrepel 包的 geom_text_repel() 中使用此信息。

library(tidyverse)
library(ggrepel)

z_mtcars <- data.frame(scale(mtcars[-12]))
z_mtcars$type <- rownames(mtcars)

我从this question那里借用了这个功能。感谢 JasonAizkalns。

is_outlier <- function(x) {
  return(x < quantile(x, 0.25) - 1.5 * IQR(x) | x > quantile(x, 0.75) + 1.5 * IQR(x))
}

z_mtcars %>%
pivot_longer(names_to = "variable", values_to = "value", -type) %>% 
group_by(variable) %>% 
mutate(outlier = if_else(is_outlier(value), type, NA_character_)) %>% 
ggplot(aes(x = variable, y = value, color = variable)) +
geom_boxplot() +
geom_text_repel(aes(label = outlier), na.rm = TRUE, show.legend = F) 

在下面的代码中,我们使用 geom_text 为异常值添加标签。在 geom_text 内,我们计算异常值位置并将数据过滤到异常值。一件奇怪的事情是,我必须在 boxplot.stats 中将 coef 设置为 1.4(而不是默认的 1.5),以便包含所有异常值。不知道为什么。我也从 dplyr 切换到 pivot_longer,因为 reshape2 已经过时,并且只保留了代码的相关部分。

library(tidyverse)
  
z_mtcars <- data.frame(scale(mtcars[-12]))
z_mtcars$type <- rownames(mtcars)

z_mtcars %>% 
  pivot_longer(cols=-type) %>% 
  ggplot(aes(x = name, y = value)) +
    geom_boxplot() +
    geom_text(data=. %>% 
                group_by(name) %>%  
                filter(value %in% boxplot.stats(value, coef=1.4)$out),
              aes(label=type, y=value), nudge_x=0.1, colour="red", size=3, hjust=0) +
    theme_classic() +
    expand_limits(x=12.6)