嵌套for do循环的替代方法

时间:2019-03-01 03:19:16

标签: r dataframe replace nested-loops

我有一个数据框,名称为df,包含200+个变量,具有300,000+个观察值(200+列,300000+行)

我的R代码的最终目标是找到每列的异常值,并用某个值(例如NA)替换它们。如果该值已经是NA,请跳过并继续下一个循环

for (j in 1:ncol(df)){
  outnumtext <- paste0('out_value <- boxplot.stats(df$',colnames(df[j]),')$out')
  eval(parse(text=outnumtext))

  for (k in 1:nrow(df)){

    replacetext <- paste0('
        if ((df[',k,',',j,'] %in% out_value) & !(is.na(df[',k,',',j,']))) {

          df[',k,',',j,'] <- NA

        } else if (is.na(df[',k,',',j,'])) {
          next

        } else {
          next
        }')

    eval(parse(text=replacetext))

    }
  }

我发现在r中使用for循环并遍历每一列中的每一行都大大降低了运行速度。有其他替代方法吗?

非常感谢您!

编辑P / S:实际代码不仅仅是用NA代替异常值,而且还具有基于多种条件(如果&if else条件将相应执行的话)的几种处理方式。但是我的目标是找到减少运行时间的可能选择,因此我尝试了尽可能简化我的原始代码以达到关键点

1 个答案:

答案 0 :(得分:1)

您不想为此使用循环。您可以尝试dplyr::mutate_all()

在超过30万行时,它仍然会很慢,但应该比循环更好。

library(dplyr)
df <- df %>% 
  mutate_all(funs(ifelse(. %in% boxplot.stats(.)$out, NA, .)))

示例:

exdata <- structure(list(x = c(200, 6, 8, 2, 7, 1, 4, 9, 3, 5, 1000), 
                         y = c(300, 1, 18, 3, 2, 16, 14, 9, 11, 6, 100)), 
                         row.names = c(NA, -11L), 
                         class = "data.frame")

exdata

      x   y
1   200 300
2     6   1
3     8  18
4     2   3
5     7   2
6     1  16
7     4  14
8     9   9
9     3  11
10    5   6
11 1000 100

data1 %>% 
  mutate_all(funs(ifelse(. %in% boxplot.stats(.)$out, NA, .)))

    x  y
1  NA NA
2   6  1
3   8 18
4   2  3
5   7  2
6   1 16
7   4 14
8   9  9 
9   3 11
10  5  6
11 NA NA