Remplacer for par une fonction

Postez ici vos questions, réponses, commentaires ou suggestions - Les sujets seront ultérieurement répartis dans les archives par les modérateurs

Modérateur : Groupe des modérateurs

Nelly ROZAS
Messages : 4
Enregistré le : 10 Mai 2007, 21:53

Remplacer for par une fonction

Messagepar Nelly ROZAS » 15 Mai 2007, 10:50

Bonjour,

Je suis débutante en R et je voudrais savoir est-ce que ce serait possible de transformer ma boucle for ci dessous en fonction car je souheterai que le calcul prenne moins de temps.

Mon probleme : j'ai un fichier de donnée avec environ 100000 lignes et 45 colonnes et je souheterai faire le calcul suivant:

A B C
[1,] 1 1 1
[2,] 2 2 2
[3,] 3 3 3
[4,] 4 4 4
[5,] 5 5 5
[6,] 6 6 6
[7,] 7 7 7
[8,] 8 8 8
[9,] 9 9 9
[10,] 10 10 10


spl = A1-A2-B1+B2 puis après A2-A3-B2+B3 ainsi de suite ça 100000 fois puis je passe à la colonne A versus C (mais ça je pense je peux garder un for)

Moi je fais ça:

Code : Tout sélectionner

#Initialisation de mes lignes
A1<-1;B1<-1;
#nl : nombre de lignes (100000)

for(i in 1:nl)
 {# boucle pour lignes
     A2<-A1+1;B2=B1+1;
    # calcul le splicing des lignes
    X <- FicBase[A1:A2,col1]; Y <- FicBase [B1:B2,col2];

    myfun <- function(A,B){
    SPL <- A[1]-A[2]-(B[1]-B[2])
    return(SPL);
 }
w<-myfun(X,Y)



Merci d'avance pour votre aide en espérant être assez claire
:( nelly

Nicolas Péru
Messages : 1408
Enregistré le : 07 Aoû 2006, 08:13

Messagepar Nicolas Péru » 15 Mai 2007, 11:01

j'ai pas vraiment le temps de te faire un code mais peut être qu'en rédigeant la fonction juste pour un ligne (en gros ce que tu as rédigé mais sans la boucle), et en utilisant la fonction apply() en ligne tu devrais pouvoir faire ça beaucoup plus vite. Regardes l'aide la fonction apply()

Si tu as beoin d'aide demande ;)

bon courage

Nicolas

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Messagepar Logez Maxime » 15 Mai 2007, 12:07

Bonjour,

Voila une ligne de commande qui devrait te simplifier les choses :

Code : Tout sélectionner

# un jeu de données simulées
FicBase <- matrix(rpois(500000,4),100000,5)
FicBase[1:6,]
     [,1] [,2] [,3] [,4] [,5]
[1,]    6    6    3    1    7
[2,]    6    5    4    5    3
[3,]    2    4    5    2    3
[4,]    3    6    3    2    3
[5,]    5    5    3    3    4
[6,]    6    5    3    2    2

# le même calcul de w
w <- sapply(1:(100000-1),function(x){FicBase[x,1]-FicBase[x+1,1]-FicBase[x,2]+FicBase[x+1,2]})


FicBase état ton tableau, x étant le numéro de ligne. Le temps de calcul est beaucoup plus court quand tu te sers des fonctions apply, lapply ... De plus ta fonction contient quelques erreurs qui ne te permettaient pas de faire tout ces calculs. Je t'en donne une version qui fait la même chose que la ligne du dessus mais en bien plus long.

Code : Tout sélectionner

A1<-1;B1<-1;
nl <- 100000  # nombre de lignes (100000)

w <- NULL
for(i in 1:(nl-1)) # n-1 car tu ne peux pas faire plus que n-1 comparaisons
 {# boucle pour lignes
     A2<-A1+1;B2=B1+1;
    # calcul le splicing des lignes
    X <- FicBase[A1:A2,1]; Y <- FicBase [B1:B2,2];

    myfun <- function(A,B){  # je te conseillerai de faire sortir ta fonction de la boucle puisqu'elle ne change pas
    SPL <- A[1]-A[2]-(B[1]-B[2])
    return(SPL);
 }
w<-c(w,myfun(X,Y)) # sinon tu ne conserves que la valeur de ton calcul en cours
A1 <- A1+1 # si tu ne le mets pas tu vas faire 100000 fois le même calcul entre la valeur 1 et 2 # idem
B1 <- B1+1
}


Si tu veux faire toutes les comparaisons possibles entre colonne :

Code : Tout sélectionner

# ici je compare les 5 colonnes de mon tableau 2 à 2 soit au total 10 comparaisons
perm <- combn(5,2)
perm
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]    1    1    1    1    2    2    2    3    3     4
[2,]    2    3    4    5    3    4    5    4    5     5

test <- apply(perm,2, function(y) {
  w <- sapply(1:(100000-1),function(x){FicBase[x,y[1]]-FicBase[x+1,y[1]]-FicBase[x,y[2]]+FicBase[x+1,y[2]]})
  return(w)
  }
)

colnames(test) <- apply(perm,2,paste,collapse="-")
test[1:5,]
     1-2 1-3 1-4 1-5 2-3 2-4 2-5 3-4 3-5 4-5
[1,]  -1   1   4  -4   2   5  -3   3  -5  -8
[2,]   3   5   1   4   2  -2   1  -4  -1   3
[3,]   1  -3  -1  -1  -4  -2  -2   2   2   0
[4,]  -3  -2  -1  -1   1   2   2   1   1   0
[5,]  -1  -1  -2  -3   0  -1  -2  -1  -2  -1


Comparer la première et la deuxième colonne prend plus d'une minute avec la boucle alors que faire les 10 comparaisons de colonne 2 à 2 prends 23 secondes sur mon PC.

En espérant t'avoir aidé un peu.

Maxime

Nelly ROZAS
Messages : 4
Enregistré le : 10 Mai 2007, 21:53

Messagepar Nelly ROZAS » 15 Mai 2007, 14:00

Merci beaucoup Nicolas,

J'ai fait un tableau tabSplice où dans chaque ligne j'ai mes 4 valeurs et ensuite j'applique ma fonction apply sur ces lignes et je voudrais récupérer mes valeurs dans un tableau car j'ai une autre boucle juste au dessus;

le problème est que j'ai une erreur et je n'arrive pas à la résoudre, pourtant avant je crée d'abord mon tableau.

Erreur:

myTissus[,1]<- spl
Erreur dans myTissus[, 1] <- spl : le nombre d'objets à remplacer n'est pas multiple de la taille du remplacement


Code : Tout sélectionner

myTissus =array(,dim=c(nblines,nbrcol))
for(j in 1:nbrcol){
# nbrcol : nombre colonnes
# Traitement des lignes et 2 colonnes (calcul)
psA1<- FicBase[1:nblines-1,col1]
psB1<- FicBase[1:nblines-1,col2]
psA2 <- FicBase[2:nblines,col1]
psB2 <- FicBase[2:nblines,col2]

tabSplice <- array(c(psA1,psB1,psA2,psB2),dim=c(nblines-1,4))
   
showSplice <- function(Z){
SPL <- Z[1]-Z[2]- Z[3]+ Z[4]
return(SPL)}

spl<- apply(tabSplice,1,showSplice)
myTissus[,j]<- apply(subSplice,1,showSplice)

}


Sinon je vais analyser la solution de Maxime car ça se rapproche de mon problème et je vous tiendrai au courant.

Merci encore à tous!!!!

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Messagepar Logez Maxime » 15 Mai 2007, 14:15

Re,

Le problème ici c'est que tu ne peux faire que n-1 comparaisons si tu as 10 lignes tu ne peux qu'avoir 9 comparaisons, donc la dimension de ton array ne va pas il te faut dim=c(nlignes-1,ncol). De plus sort tout ce qui n'est pas nécessaire de répéter de la boucle comme showSplice <- ..., à priori ta fonction ne changera pas donc sort la, etc.

Maxime

Nelly ROZAS
Messages : 4
Enregistré le : 10 Mai 2007, 21:53

Messagepar Nelly ROZAS » 17 Mai 2007, 13:21

Bonjour Maxime,

Merci pour le script et les corrections, ça me prend 3h pour 10000 lignes (avec mes données) mais je crois c'est parce j'ai des chiffres avec parfois plus de 7 chiffres après la virgule , bon je vais regarder dans la doc si je trouve pas quelque chose pour tronquer mes chifres.

C'est pas évident d'apprendre tout seul R, je me complique la vie alors qu'il y a des formules toutes simples :lol: .

Bon encore merci de ton aide.

François Bonnot
Messages : 537
Enregistré le : 10 Nov 2004, 15:19
Contact :

Messagepar François Bonnot » 21 Mai 2007, 08:35

Bonjour,
Pour calculer la différence entre éléments successifs mieux vaut utiliser la fonction diff. Par exemple on peut efficacement remplacer

Code : Tout sélectionner

w <- sapply(1:(100000-1),function(x){FicBase[x,1]-FicBase[x+1,1]-FicBase[x,2]+FicBase[x+1,2]})

par

Code : Tout sélectionner

w <- diff(FicBase[,2]-FicBase[,1])

Laurent Michelizza
Messages : 6
Enregistré le : 07 Mar 2007, 19:45

Messagepar Laurent Michelizza » 30 Mai 2007, 16:46

Bonjour,
Ca ne pose pas de problemes d'utiliser une matrice declaree a l'exterieur de la fonction (comme dans l'exemple ci dessus)?

La plupart des applicationsque j'ai vu passe la matrice en argument, mais dans ce cas je ne vois pas comment transformer l'exemple suivant...

Code : Tout sélectionner

# un jeu de données simulées
FicBase <- matrix(rpois(500000,4),100000,5)

# le même calcul de w
w <- sapply(1:(100000-1),function(x){FicBase[x,1]-FicBase[x+1,1]-FicBase[x,2]+FicBase[x+1,2]})


Laurent

Logez Maxime
Messages : 3138
Enregistré le : 26 Sep 2006, 11:35

Messagepar Logez Maxime » 30 Mai 2007, 17:25

Bonjour,


A priori ça ne pose pas de problème (extrait de http://pbil.univ-lyon1.fr/R/cours/lang03.pdf)
A l’intérieur d’une fonction la variable est d’abord recherchée à l’intérieur de la fonction, à savoir :
Les variables définies comme arguments de cette fonction
Les variables définie à l’intérieur de la fonction
Si une variable n’est pas trouvée à l’intérieur de la fonction, elle est recherchée en dehors de la fonction. Le détail de ce mécanisme est complexe, mais tout ce que l’on a à retenir est que :
Une variable définie à l’extérieur de la fonction est accessible aussi dans la fonction.
Si deux variables avec le même nom sont définies à l’intérieur et à l’extérieur de la fonction, c’est la variable locale qui sera utilisée.
Une erreur aura lieu si aucune variable avec le nom demandé n’est trouvée.

Après tout dépend ce que tu cherches à faire.

Maxime

Laurent Michelizza
Messages : 6
Enregistré le : 07 Mar 2007, 19:45

Messagepar Laurent Michelizza » 31 Mai 2007, 12:04

Merci pour le lien qui est plutot interessant.

En fait ce qui me derange c'est surtout le fait d'utiliser des variables externes a l'interieur d'une fonction sachant que j'ai beaucoup plus utilise d'autres types de langages qui ne le permettent pas...
Cela dit pour ce que je veux faire ca m'arrange! :P


Retourner vers « Questions en cours »

Qui est en ligne

Utilisateurs parcourant ce forum : Google [Bot] et 1 invité

cron