如果从数据框中的每一列中检测到离群值(例如 99% 分位数),则删除完整行

Remove COMPLETE row if Outlier (e.g. 99% Quantile) is Detected from EVERY Column in a Dataframe

假设这是我的数据框。

MyData <- data.frame(
+     X = sample(10:100, 21),
+     Y = sample(10:100, 21),
+     Z = sample(10:100, 21)
+ )

我了解如何使用 sapplyapply 打印每列的分位数:

> apply( MyData , 2, quantile , .99 , na.rm = TRUE )
   X    Y    Z 
98.0 97.6 92.8 
> sapply( MyData , quantile , .99 , na.rm = TRUE )
X.99% Y.99% Z.99% 
 98.0  97.6  92.8

但是,如果检测到高于此阈值的值,则删除整个 ROW(对于每个列都是如此)对我不起作用。任何解决方案 - 有或没有 dplyr 都表示赞赏。

这是一个使用 cut 的解决方案:

set.seed(123)
MyData <- data.frame(
    X = sample(10:100, 21),
    Y = sample(10:100, 21),
    Z = sample(10:100, 21)
)
head(MyData, 4)
#>    X  Y  Z
#> 1 36 73 47
#> 2 80 67 43
#> 3 46 98 23
#> 4 87 99 22
apply(MyData, 2, quantile, .95)
#>  X  Y  Z 
#> 97 98 83
tmp1 <- apply(MyData, 2, function(x) cut(x, c(-Inf, quantile(x, probs = .95), Inf), labels = FALSE))
MyData[tmp1 == 2] <- NA
head(MyData, 4)
#>    X  Y  Z
#> 1 36 73 47
#> 2 80 67 43
#> 3 46 98 23
#> 4 87 NA 22
head(na.omit(MyData), 4)
#>    X  Y  Z
#> 1 36 73 47
#> 2 80 67 43
#> 3 46 98 23
#> 5 91 71 30

您可以与分位数进行比较以获得 TRUE 和 FALSE 矩阵,然后对没有列包含 TRUE 的行进行子集化

MyData[!apply(apply(MyData, 2, function(x) x > quantile(x, 0.99)), 1, any), ]

数据:

set.seed(26L)
MyData <- as.matrix(data.frame(
    X = sample(10:100, 21),
    Y = sample(10:100, 21),
    Z = sample(10:100, 21)
))

我们可以使用 dplyr 中的 filter_all 来为每一列的条件过滤行。 all_vars表示所有列都满足条件。

set.seed(123)
MyData <- data.frame(
  X = sample(10:100, 21),
  Y = sample(10:100, 21),
  Z = sample(10:100, 21)
)

head(MyData)
#   X  Y  Z
# 1 36 73 47
# 2 80 67 43
# 3 46 98 23
# 4 87 99 22
# 5 91 71 30
# 6 13 56 50

library(dplyr)

MyData2 <- MyData %>% filter_all(all_vars(. <= quantile(., 0.99, na.rm = TRUE)))

head(MyData2)
#    X  Y  Z
# 1 36 73 47
# 2 80 67 43
# 3 46 98 23
# 4 91 71 30
# 5 13 56 50
# 6 54 60 32