R код слишком долго для запуска - PullRequest
4 голосов
/ 06 сентября 2011

У меня работает следующий код, и он занимает много времени. Как я узнаю, что он все еще выполняет свою работу или он где-то застрял.

noise4<-NULL;
for(i in 1:length(noise3))
{
    if(is.na(noise3[i])==TRUE)
    {
    next;
    }
    else
    {
    noise4<-c(noise4,noise3[i]);
    }
}

noise3 - вектор с 2418233 точками данных.

Ответы [ 4 ]

10 голосов
/ 06 сентября 2011

Вы просто хотите удалить значения NA.Сделайте это так:

noise4 <- noise3[!is.na(noise3)]

Это будет почти мгновенно.

Или, как предлагает Джошуа, более читабельная альтернатива:

noise4 <- na.omit(noise3)

Ваш код был медленнымпотому что:

  1. Используются явные циклы, которые, как правило, работают медленно при интерпретаторе R.
  2. Вы перераспределяете память каждую итерацию.

Перераспределение памятивероятно, самый большой недостаток для вашего кода.

5 голосов
/ 06 сентября 2011

Я хотел проиллюстрировать преимущества предварительного выделения ресурсов, поэтому я попытался запустить ваш код ... но я убил его через ~ 5 минут.Я рекомендую вам использовать noise4 <- na.omit(noise3), как я сказал в моих комментариях.Этот код предназначен исключительно для иллюстративных целей.

# Create some random data
set.seed(21)
noise3 <- rnorm(2418233)
noise3[sample(2418233, 100)] <- NA

noise <- function(noise3) {
  # Pre-allocate
  noise4 <- vector("numeric", sum(!is.na(noise3)))
  for(i in seq_along(noise3)) {
    if(is.na(noise3[i])) {
      next
    } else {
      noise4[i] <- noise3[i]
    }
  }
}

system.time(noise(noise3)) # MUCH less than 5+ minutes
#    user  system elapsed 
#    9.50    0.44    9.94 

# Let's see what we gain from compiling
library(compiler)
cnoise <- cmpfun(noise)
system.time(cnoise(noise3))  # a decent reduction
#    user  system elapsed 
#    3.46    0.49    3.96 
4 голосов
/ 06 сентября 2011

Другие ответы дали вам намного, намного лучшие способы выполнить задачу, которую вы на самом деле намеревались выполнить (удалив значения NA в ваших данных), но ответ на конкретный вопрос, который вы задали («как мне это сделать?»).знать, работает ли R на самом деле или он вместо этого застрял? ") это ввести некоторые выходные (cat) операторы в ваш цикл следующим образом:

rpt <- 10000  ## reporting interval
noise4<-NULL;
for(i in 1:length(noise3))
{
    if (i %% rpt == 0) cat(i,"\n")
    if(is.na(noise3[i])==TRUE)
    {
    next;
    }
    else
    {
    noise4<-c(noise4,noise3[i]);
    }
}

Если вы запустите этот код, вы можетесразу же увидеть, что он радикально замедляется по мере того, как попадает в цикл дальше (следствие неудачного предварительного выделения пространства) ...

2 голосов
/ 07 сентября 2011

Все остальные дали правильные способы решения той же проблемы, так что вам не нужно беспокоиться о скорости.@BenBolker также дал хороший указатель относительно регулярного вывода.

Еще одна вещь, на которую следует обратить внимание, это то, что если вы окажетесь в цикле, вы можете выйти из него и найти значение i.Если предположить, что повторный запуск с этого значения i не повредит, то есть использование этого значения дважды не составит проблемы, вы можете перезапустить.Или вы можете просто закончить работу, как заявили другие.

Отдельный трюк заключается в том, что если цикл медленный (и не может быть векторизован, иначе вы не хотите выходить из цикла), И у вас нет отчетов, вы все равно можете найти внешний метод, чтобы узнать, действительно ли R потребляет циклы на вашем компьютере.В Linux команда top - ваш лучший выбор.В Windows диспетчер задач сделает свое дело (я предпочитаю использовать программу Process Explorer SysInternals / Microsoft).«top» также существует на Mac, хотя я считаю, что есть и другие более популярные инструменты.

Еще один совет: если у вас действительно длинный цикл, я настоятельно рекомендую регулярно сохранять результаты.Я обычно создаю файл с именем вроде: myPrefix_YYYYMMDDHHMMSS.rdat.Таким образом, все может пойти в ад, и вы все равно можете начать свой цикл с того места, где остановились.

Я не всегда повторяю, но когда я это делаю, я использую эти приемы.Будь спокоен, друг мой.

...