Петли неэффективности в R - PullRequest
5 голосов
/ 28 июня 2010

Доброе утро,

Я работаю в R несколько месяцев и должен убедиться, что время выполнения моего кода не слишком велико, потому что я анализирую большие наборы данных.

Следовательно, я пытался использовать как можно больше векторизованных функций.

Тем не менее, я все еще удивляюсь чему-то.

Что дорого стоит в R, не так ли сам цикл?Я имею в виду, что проблема возникает, когда вы начинаете модифицировать переменные в цикле, например, это правильно?

Поэтому я подумал, что если вам просто нужно запустить функцию для каждого элемента (вас на самом деле не волнуетрезультат).Например, для записи данных в базу данных.Что вы должны сделать?

1) использовать mapply, нигде не сохраняя результат?

2) сделать цикл над вектором и применить только f (i) к каждому элементу?

3) есть ли лучшая функция, которую я мог бы пропустить?

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

Как насчет пакета foreach?Испытывали ли вы какое-либо улучшение производительности, используя его?

Ответы [ 2 ]

6 голосов
/ 28 июня 2010

Просто пара комментариев.Цикл for примерно такой же быстрый, как apply и его варианты, и реальные ускорения наступают, когда вы максимально векторизуете свою функцию (то есть, используя низкоуровневые циклы, а не apply, чтопросто скрывает петлю for).Я не уверен, что это лучший пример, но рассмотрим следующее:

> n <- 1e06
> sinI <- rep(NA,n)
> system.time(for(i in 1:n) sinI[i] <- sin(i))
   user  system elapsed 
  3.316   0.000   3.358 
> system.time(sinI <- sapply(1:n,sin))
   user  system elapsed 
  5.217   0.016   5.311 
> system.time(sinI <- unlist(lapply(1:n,sin),
+       recursive = FALSE, use.names = FALSE))
   user  system elapsed 
  1.284   0.012   1.303 
> system.time(sinI <- sin(1:n))
   user  system elapsed 
  0.056   0.000   0.057 

В одном из комментариев ниже, Марек указывает, что часть времени цикла for, занимающая много времени, на самом деле]<- часть:

> system.time(sinI <- unlist(lapply(1:n,sin),
+       recursive = FALSE, use.names = FALSE))
   user  system elapsed 
  1.284   0.012   1.303 

Узкие места, которые не могут быть немедленно векторизованы, могут быть переписаны на C или Fortran, скомпилированы с R CMD SHLIB, а затем подключены с помощью .Call, .Cили .Fortran.

Также см. эти ссылки для получения дополнительной информации об оптимизации цикла в R. Также ознакомьтесь со статьей "Как можно избежатьЭта петля или сделать ее быстрее? " в R News.

4 голосов
/ 23 марта 2011

vapply позволяет избежать постобработки, требуя указать возвращаемое значение.Оказывается, в 3,4 раза быстрее, чем цикл for:

> system.time(for(i in 1:n) sinI[i] <- sin(i))
   user  system elapsed 
   2.41    0.00    2.39 

> system.time(sinI <- unlist(lapply(1:n,sin), recursive = FALSE, use.names = FALSE))
   user  system elapsed 
   1.46    0.00    1.45 

> system.time(sinI <- vapply(1:n,sin, numeric(1)))
   user  system elapsed 
   0.71    0.00    0.69 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...