Альтернатива вложенному циклу do - PullRequest
0 голосов
/ 01 марта 2019

У меня есть фрейм данных с именем 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))

    }
  }

Я обнаружил, что использование цикла for в r и циклическое прохождение всех строк в каждом столбце значительно замедляетБег.Есть ли альтернативы этому?

Заранее большое спасибо!

Редактировать P / S: Настоящий кодекс не просто заменяет выбросы NA, но имеет несколько способов борьбы на основенесколько условий (где if & if else условия будут выполнены соответственно).Однако моя цель - найти возможную альтернативу в сокращении времени выполнения, поэтому я постарался максимально упростить свой исходный код, чтобы добраться до основного момента

1 Ответ

0 голосов
/ 01 марта 2019

Вы не хотите использовать петли для этого.Вы можете попробовать dplyr::mutate_all().

Это будет медленным на 300K + строк, но должно быть лучше, чем цикл.

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
...