【问题标题】:How to delete outliers from a QQ-plot graph made with ggplot()?如何从使用 ggplot() 制作的 QQ 图中删除异常值?
【发布时间】:2023-03-27 19:15:01
【问题描述】:

我有一个二维数据集(例如列 x 和 y)。我使用以下函数来绘制此数据的 QQ 图。

# Creating a toy data for presentation

df = cbind(x = c(1,5,8,2,9,6,1,7,12), y = c(1,4,10,1,6,5,2,1,32))

# Plotting the QQ-plot

df_qq = as.data.frame(qqplot(df[,1], df[,2], plot.it=FALSE))

ggplot(df_qq) + 
   geom_point(aes(x=x, y=y), size = 2) + 
   geom_abline(intercept = c(0,0), slope = 1)

这是结果图:

我的问题是,如何避免绘制最后一点(即 (12,32))?我宁愿不手动删除它,因为我有几个这样的数据对,而且每个数据对都有类似的异常值。我想做的是编写一个代码,以某种方式识别距离 45 度线太远的点,并从 df_qq 中消除它们(例如,如果它比到 45 度线的平均距离远 5 倍,它可以是被淘汰)。我的主要目标是使图表更易于阅读。当异常值没有被消除时,QQ 图的更规则部分占据了图形的太小部分,这使我无法直观地评估除异常值之外的两个向量的相似性。

我将不胜感激。

【问题讨论】:

  • 检查coord_cartesian()

标签: r ggplot2 outliers quantile


【解决方案1】:

有一个 CRAN 包,referenceIntervals,它使用库克的距离来检测异常值。通过将其应用于df_qq$y 的值,它可以为要删除的df_qq 提供一个索引。

library(referenceIntervals)

out <- cook.outliers(df_qq$y)$outliers
i <- which(df_qq$y %in% out)

ggplot(df_qq[-i, ]) + 
  geom_point(aes(x=x, y=y), size = 2) + 
  geom_abline(intercept = c(0,0), slope = 1)

编辑。

根据 OP 的评论,

但是据我了解这个函数不看 x & y 的关系,

也许只有当它们在一个向量中是异常值而不是两个向量中都是异常值时才需要使用以下函数来删除异常值。

cookOut <- function(X){
  out1 <- cook.outliers(X[[1]])$outliers
  out2 <- cook.outliers(X[[2]])$outliers
  i <- X[[1]] %in% out1
  j <- X[[2]] %in% out2
  w <- which((!i & j) | (i & !j))
  if(length(w)) X[-w, ] else X
}

使用第二个数据集进行测试,即评论中的那个。
额外的向量,id 只是为了让分面更容易。

df1 <- data.frame(x = c(1,5,8,2,9,6,1,7,12), y = c(1,4,10,1,6,5,2,1,32))
df2 <- data.frame(x = c(1,5,8,2,9,6,1,7,32), y = c(1,4,10,1,6,5,2,1,32))

df_qq1 = as.data.frame(qqplot(df1[,1], df1[,2], plot.it=FALSE))
df_qq2 = as.data.frame(qqplot(df2[,1], df2[,2], plot.it=FALSE))

df_qq_out1 <- cookOut(df_qq1)
df_qq_out2 <- cookOut(df_qq2)
df_qq_out1$id <- "A"
df_qq_out2$id <- "B"
df_qq_out <- rbind(df_qq_out1, df_qq_out2)

ggplot(df_qq_out) + 
  geom_point(aes(x=x, y=y), size = 2) + 
  geom_abline(intercept = c(0,0), slope = 1) +
  facet_wrap(~ id)

【讨论】:

  • 但据我了解,此函数不考虑 x 和 y 之间的关系,例如,如果 df 是 df = cbind(x = c(1,5,8,2,9,6,1,7,32), y = c(1,4,10,1,6,5,2,1,32)) 我不想将 (32,32) 标记为异常值并且我不想摆脱它。然而,cook.outliers 函数仍然返回 32 作为异常值。
  • @ElifCansuAkoğuz 也许编辑中的功能是你想要的。看看是不是,然后说点什么。
  • someone answers你的问题时该怎么办。
猜你喜欢
  • 2016-04-25
  • 2013-11-10
  • 2016-07-19
  • 2020-04-21
  • 1970-01-01
  • 2020-05-06
  • 2021-12-20
  • 1970-01-01
相关资源
最近更新 更多