2009-10-13 9 views
2

Je me demandais s'il est possible d'utiliser la fonction lapply() pour modifier la valeur de l'entrée, semblable à:Pouvez-vous utiliser la fonction lapply() pour modifier la valeur de l'entrée?

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

Je cherche quelque chose qui ressemble à une boucle for(), mais en utilisant l'infrastructure lapply(). Je n'ai pas pu obtenir rapply() pour le faire.

La raison en est que la fonction «réelle» a2 est une fonction difficile qui n'a besoin d'être évaluée que si la valeur de a1 [i-1] répond à certains critères.

re-phrasé: donc je suis en train de remplacer le for() dans le code ci-dessous par un lapply() - Type chose:

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

La R liste de diffusion a conseillé à la recherche jusqu'à la réduire () fonction .... comme dans:

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

qui donne le même résultat que cumprod (a1) ... mais il est encore plus lent que la boucle:

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 
> 

Une idée?

+0

Je ne pense pas que je suis ce que vous voulez faire. Est-ce que a1 [i] (ce que vous calculez) dépend de a1 [i-1]? Si c'est le cas, je pense qu'il est préférable d'utiliser des boucles. Si ce n'est pas le cas, il serait préférable de subdiviser le vecteur et de faire la fonction dans cette partie. –

+0

Est-ce que ceux-ci devraient être équivalents dans votre dernière ligne ci-dessus: cbind (a1, cumprod (a2))? Pour autant que je sache, ils ne correspondent pas. – Shane

+0

Shane: c'est le problème: la fonction looop() (voir article) donne le même résultat que cumprod .... mais pas la version lapply(). Je veux récursivement appliquer une fonction (plus compliquée que la multiplication) qui utilise la valeur de l'évaluation précédente sur un vecteur ...et ne peut pas trouver un moyen d'éviter la boucle – user189035

Répondre

2

Modifier: Après votre clarification: non, je ne crois pas que vous pouvez utiliser une fonction apply pour faire quelque chose de manière récursive comme ça. Le point entier d'une fonction d'application est qu'elle s'applique à travers le vecteur/la matrice en même temps.

Vous pouvez également vouloir look at this related question on stackoverflow.

Ma vieille réponse:

Essayez ceci:

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

Contrairement à une boucle for, vous devez passer dans une référence à tout ce que vous avez besoin dans un lapply. Le retour est également une liste, vous devez donc le renvoyer sous la forme que vous voulez.

Vous pourriez également vouloir regarder l'emballage de plyr pour des manières faciles de faire ce genre de chose.

Au-delà, vous pouvez faire votre opération sans boucle:

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

En d'autres termes, ces déclarations sont complètement équivalentes:

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

Mais la première version est préférable car il n'a pas itérations.

+0

nop: je n'ai pas été clair. Voir reformulation ci-dessus :) – user189035