我正在解决R练习,但我认为我可以使这个代码更优雅或更简单.我正在使用ggplot2中的钻石数据集.我必须从数字变量中删除异常值,并且异常值对我来说是一行,其中任何数值变量高于或低于中位数+/- 3倍MAD(中位数绝对偏差).我的实际代码是非常手动的:
library(dplyr)
filter(numeric.vars,
carat > median(carat) - 3 * mad(carat),
carat < median(carat) + 3 * mad(carat),
depth > median(depth) - 3 * mad(depth),
depth < median(depth) + 3 * mad(depth),
table > median(table) - 3 * mad(table),
table < median(table) + 3 * mad(table),
price > median(price) -3 * mad(price),
price < median(price) +3 * mad(price),
x > median(x) - 3 * mad(x),
x < median(x) + 3 * mad(x),
y > median(y) - 3 * mad(y),
y < median(y) + 3 * mad(y),
z > median(z) - 3 * mad(z),
z < median(z) + 3 * mad(z)) -> clean
Run Code Online (Sandbox Code Playgroud)
我应该做什么样的事情apply(numeric.vars,1, myCustomFunction)来应用每一行的条件?虽然按行,但我不知道数据属于哪一列.
我们创建numeric列的逻辑索引('numeric.vars'),循环遍历数据集的那些列,使用median和应用条件mad,并检查所有变量是否符合每行的条件(使用Reduce和&)来创建逻辑vector('i1')我们用来对"钻石"数据集的行进行子集化.
numeric.vars <- sapply(diamonds, is.numeric)
i1 <- Reduce(`&`, lapply(diamonds[numeric.vars], function(v)
(v > median(v) - 3* mad(v)) & (v < median(v) + 3 * mad(v))) )
SubDiam <- diamonds[i1,]
nrow(SubDiam)
#[1] 44736
Run Code Online (Sandbox Code Playgroud)
基于OP的代码
nrow(clean)
#[1] 44736
Run Code Online (Sandbox Code Playgroud)
该assertr软件包包含一个within_n_mads有用的功能.但是,要在其通常的框架之外使用它,需要做一些工作.within_n_mads(3)返回一个函数,该函数在传递向量时将创建一个新函数.该功能测试各个值.
因此,稍微purrr(dplyr如果你喜欢,与之杂交),
library(purrr)
library(assertr)
diamonds %>% keep(is.numeric) %>% # Subset to numeric columns
# Change all values to logical of whether it is within 3 mads
dmap(~within_n_mads(3)(.x)(.x)) %>%
# Filter diamonds to rows where all columns of . are TRUE
reduce(`&`) %>% diamonds[., ]
## # A tibble: 44,736 × 10
## carat cut color clarity depth table price x y z
## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl>
## 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43
## 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31
## 3 0.29 Premium I VS2 62.4 58 334 4.20 4.23 2.63
## 4 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75
## 5 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48
## 6 0.24 Very Good I VVS1 62.3 57 336 3.95 3.98 2.47
## 7 0.26 Very Good H SI1 61.9 55 337 4.07 4.11 2.53
## 8 0.23 Very Good H VS1 59.4 61 338 4.00 4.05 2.39
## 9 0.30 Good J SI1 64.0 55 339 4.25 4.28 2.73
## 10 0.23 Ideal J VS1 62.8 56 340 3.93 3.90 2.46
## # ... with 44,726 more rows
Run Code Online (Sandbox Code Playgroud)