【问题标题】:Find outliers by Standard Deviation from mean, replace with NA in large dataset (6000+ columns)通过均值的标准偏差查找异常值,在大型数据集中(6000 列以上)替换为 NA
【发布时间】:2020-04-21 15:07:13
【问题描述】:

我找到了一些与我正在寻找的类似的答案,但代码不起作用。

我需要用 NA 或 NULL 替换每列的所有异常值(根据我们的目的定义为距离平均值超过 2 个 SD)。我正在尝试对所有列进行迭代,计算每列的异常值并替换这些值。

披露:我也知道统计数据对去除异常值有强烈的看法,并且考虑到 SD 的计算包括在这种情况下的异常值,因此使用 SD 作为排除它们的措施。这些是我们的统计学家给我的指示,所以我现在正在努力。

这是我的数据集的一瞥:

data

Group sp.Q13813.SPTN1_HUMAN sp.O14773.TPP1_HUMAN sp.P11137.MTAP2_HUMAN
1 Premutation           10713983468            367492324            2134747097
2 Premutation           10789498495            343303410            2677825476
3 Premutation           11134883489            383589325            2132552280
4 Premutation            9723552595            269965000            2262740921
5 Premutation           11175156282            359864993            1419225650
6 Premutation           10959077349            258095035            3343267633
7 Premutation           10770809133            331554977            2763604046
8 Premutation           11098182537            344384433            2198718886

我尝试了包含 scale() 函数的代码,但是当我执行以下函数时,我发现它替换了列平均值 2 SD 以内的值,并且它使我的代码保持缩放格式。我对这个函数不太熟悉,也不知道如何将它恢复到原始数据点,即使它正在替换正确的异常值。

方法尝试#1

# take note of order for column names
data.names_P <- colnames(data)


# scale all numeric columns
data.numeric.Pre <- select_if(data, is.numeric) %>% # subset of numeric columns
  mutate_all(scale)                             # perform scale separately for each column
data.numeric.Pre[data.numeric.Pre > 2] <- 99999 # set values larger than 2 to NA (none in this example)

# combine results with subset data frame of non-numeric columns
data.Pre <- data.frame(select_if(data, function(x) !is.numeric(x)),
                   data.numeric)

# restore columns to original order
data.Pre <- data.Pre[, data.names_P]

方法尝试#2


FindOutliers <- function(data) {
  upper = (2*sd(data) + mean(data)
  lower = (mean - 2*sd(data))
  result <- which(data < upper | data > lower)
}

我知道第二次尝试不会用 NA 替换数据。

任何帮助将不胜感激。

【问题讨论】:

    标签: r replace outliers stdev


    【解决方案1】:

    您可以使用ifelse 函数,这里是一个使用dplyr 的示例,并将ifelse 函数应用于包含术语HUMAN 的所有列:

    library(dplyr)
    data %>% mutate_at(.vars = vars(contains("HUMAN")), 
                       .funs= ~ifelse(abs(.)>mean(.)+2*sd(.), NA, .))
    

    【讨论】:

    • 选择包含“人类”的变量不是我所知道的功能,这也可以工作。谢谢!
    • 不客气 ;) 作为新贡献者,您应该查看此链接:stackoverflow.com/help/someone-answers
    • 你知道如何为迭代需要跨行而不是向下运行的函数调整它吗?我知道如何为行而不是列调整 apply() 函数,但我坚持使用 dplyr mutate 函数 - 如果它甚至可能的话。
    • 您可能可以转置您的数据框(反转行和列),然后在其上应用dplyr 函数。没有数据,很难确定解决方案
    • 我在使用正常的转置功能时遇到了问题 - 当我有 >30k 行需要反转为列时,它会将我的列截断为仅 50...但能够使用WGCNA 包和 transposeBigData() 函数使您的上述推荐工作。谢谢!
    【解决方案2】:

    我们可以使用您第二次尝试的函数将数据替换为NA

    FindOutliers <- function(data) {
       mean_data <- mean(data, na.rm = TRUE)
       sd_data <- sd(data, na.rm = TRUE)
       upper = 2*sd_data + mean_data
       lower = mean_data - 2*sd_data
       replace(data, data > upper | data < lower, NA)
    }
    
    library(dplyr)
    data %>%  mutate_if(is.numeric, FindOutliers)
    #Tested it via
    #mtcars %>%  mutate_if(is.numeric, FindOutliers)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-07
      • 1970-01-01
      • 1970-01-01
      • 2013-03-24
      • 2021-04-25
      • 1970-01-01
      相关资源
      最近更新 更多