Можете ли вы использовать функцию lapply (), чтобы изменить значение ввода? - PullRequest
2 голосов
/ 13 октября 2009

Мне было интересно, возможно ли использовать функцию lapply () для изменения значения ввода, аналогично:

a1<-runif(100)
a2<-function(i){
a1[i]<-a1[i-1]*a1[i];a1[i]
}
a3<-lapply(2:100,a2)

Я ищу что-то похожее на цикл for (), но использую инфраструктуру lapply (). Я не смог получить rapply () для этого.

Причина в том, что «реальная» функция a2 - сложная функция, которую нужно оценивать, только если значение a1 [i-1] удовлетворяет некоторым критериям.

Перефразирование: поэтому я пытаюсь заменить for () в приведенном ниже коде на lapply () - тип вещи:

    a1<-runif(100)
    a2<-function(i, a1){
        a1[i]<-a1[i-1]*2
        a1[i]
    }
    a3<-as.numeric(lapply(2:100, a2, a1=a1))
#compare the output of a3 with that of a1 after the recursive loop
    a2<-a1 #saved for comparison
    for(i in 2:length(a1)){
        a1[i]<-a1[i-1]*2
    }
cbind(a1[2:100],a3)
#actually this is would be like writting a lapply() version of the cumprod() function
cbind(a1,cumprod(a2))

Список рассылки R посоветовал обратиться к функции Reduce () .... как в:

a1<-runif(100)
cadd<-function(x) Reduce("*", x, accumulate = TRUE)
cadd(a1)

, который дает тот же результат, что и cumprod (a1) ... но даже медленнее, чем цикл:

a1<-runif(100000)
cadd<-function(x) Reduce("*", x, accumulate = TRUE)
looop<-function(a1){
j<-length(a1)
    for(i in 2:j){
        a1[i]<-a1[i-1]*a1[i]
    }
a1
}

> system.time(cadd(a1))
   user  system elapsed 
  1.344   0.004   1.353 
> system.time(cumprod(a1))
   user  system elapsed 
  0.004   0.000   0.002 
> system.time(loop(a1))
   user  system elapsed 
  0.772   0.000   0.775 
> 

Есть идеи?

1 Ответ

2 голосов
/ 13 октября 2009

Редактировать: После вашего разъяснения: нет, я не верю, что вы можете использовать функцию apply для рекурсивного выполнения чего-либо подобного. Весь смысл применения функции заключается в том, что она применяется одновременно к вектору / матрице.

Вы также можете посмотреть на этот связанный вопрос по stackoverflow .

Мой старый ответ:

Попробуйте это:

a1<-runif(100)
a2<-function(i, a1){
    a1[i]<-a1[i-1]*a1[i]
    a1[i]
}
a3 <- as.numeric(lapply(2:100, a2, a1=a1))

В отличие от цикла for, вам необходимо передать ссылку на все, что вам нужно, в lapply. Возвращение также является списком, поэтому вам нужно привести его обратно в любую форму.

Возможно, вы захотите взглянуть на пакет plyr, чтобы узнать, как сделать что-то подобное.

Кроме того, вы можете выполнять свою работу без цикла:

a3 <- a1[-length(a1)] * a1[-1]

Другими словами, эти утверждения полностью эквивалентны:

> all((a1[-length(a1)] * a1[-1]) == as.numeric(lapply(2:100, a2, a1=a1)))
[1] TRUE

Но первая версия предпочтительнее, поскольку в ней нет итераций.

...