如何让这个R代码更优雅?

dav*_*ppo 2 r dplyr

我正在解决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)来应用每一行的条件?虽然按行,但我不知道数据属于哪一列.

akr*_*run 5

我们创建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)


ali*_*ire 5

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)