2009-10-13 4 views
2

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

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

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

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

повторно фразировка: так я пытаюсь заменить на() в коде ниже по 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 консультировал взираем Уменьшить () функция .... как в:

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 
> 

Любая идея?

+0

Я не думаю, что я следую тому, что вы хотите. А1 [i] (то, что вы вычисляете) зависит от a1 [i-1]? Если это так, я думаю, что лучше использовать циклы. Если нет, было бы лучше подмножить вектор и выполнить функцию в этой части. –

+0

Должны ли они быть эквивалентными в вашей последней строке выше: cbind (a1, cumprod (a2))? Насколько я могу судить, они не совпадают. – Shane

+0

Шейн: вот в чем проблема: функция looop() (см. Сообщение) дает тот же результат, что и cumprod .... но версия lapply() этого не делает. Я хочу рекурсивно применить функцию (более сложную, чем умножение), которая использует значение предыдущей оценки для вектора ...и не может найти способ избежать цикла – user189035

ответ

2

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

Вы также можете хотеть look at this related question on 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 

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

+0

nop: Я не прояснил ситуацию. См. Повторную формулировку выше :) – user189035

Смежные вопросы