IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

R Discussion :

Eviter la double boucle de programmation


Sujet :

R

  1. #1
    ced
    ced est déconnecté
    Rédacteur/Modérateur

    Avatar de ced
    Homme Profil pro
    Gestion de bases de données techniques
    Inscrit en
    Avril 2002
    Messages
    6 016
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Loiret (Centre)

    Informations professionnelles :
    Activité : Gestion de bases de données techniques
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Avril 2002
    Messages : 6 016
    Points : 23 705
    Points
    23 705
    Par défaut Eviter la double boucle de programmation
    Bonjour,

    Je pars d'un data frame (nommé deps) qui contient des départements, des cycles de visites dans ces départements, et l'année de chacun de ces cycles de visites pour chaque département :
    dep cyc visite
    33   1 1961
    40   1 1961
    19   1 1962
    32   1 1962
    47   1 1962
    46   1 1963
    ...
    63   2 1976
    15   2 1977
    33   2 1977
    03   2 1978
    09   2 1978
    11   2 1978
    ...
    Au maximum, il y a 4 cycles de visite par département (mais parfois 2 ou 3 seulement pour certains départements).

    Mon objectif est de transformer ce data frame en un autre data frame contenant les départements en lignes, les années (de la plus ancienne du premier cycle à la plus récente du 4ème cycle), et dans chaque case le nombre d'années entre l'année de la colonne et le dernier passage dans le département (cycle le plus récent).

    Avec l'exemple suivant, pour le département 33, ça donnerait :
    dep 1961 1962 1963 1964 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 
    33    1    2    3    4    6    7    8    9   10   11   12   13   14   15   16    1    2    3    4  
    
    Au passage, on démarre volontairement la différence entre les années à 1. Comme le cycle 2 du département 33 a démarré en 1973, le nombre repart à 1 sur la colonne 1973...

    J'ai bien un code pour faire ça, mais il passe par 2 boucles pour aller remplir les "cases" du data frame une à une :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    toto <- reshape(subset(deps, select = c(dep, visite, visite)), idvar = "dep", timevar = "visite", direction = "wide")
     
    names(toto) <- c("dep", unique(deps$visite))
    toto2 <- merge(toto, subset(deps, cyc == 1, select = c(dep, visite)), all.x = T)
    names(toto2)[ncol(toto2)] <- "visite1"
    toto2 <- merge(toto2, subset(deps, cyc == 2, select = c(dep, visite)), all.x = T)
    names(toto2)[ncol(toto2)] <- "visite2"
    toto2 <- merge(toto2, subset(deps, cyc == 3, select = c(dep, visite)), all.x = T)
    names(toto2)[ncol(toto2)] <- "visite3"
    toto2 <- merge(toto2, subset(deps, cyc == 4, select = c(dep, visite)), all.x = T)
    names(toto2)[ncol(toto2)] <- "visite4"
     
    toto3 <- toto2
    as.integer(names(toto3)[2:45]) < toto3$visite1
    for (i in 2:45) {
    	for (j in seq(along = 1:nrow(toto3))) {
    		if (as.integer(names(toto3)[i]) < toto3[j, "visite1"]) {
    			toto3[j, i] <- 0
    		} 
    		else if(as.integer(names(toto3)[i]) < toto3[j, "visite2"]) {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite1"] + 1
    		}
    		else if(is.na(toto3[j, "visite3"])) {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite2"] + 1
    		}
    		else if(as.integer(names(toto3)[i]) < toto3[j, "visite3"]) {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite2"] + 1
    		}
    		else if(is.na(toto3[j, "visite4"])) {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite3"] + 1
    		}
    		else if(as.integer(names(toto3)[i]) < toto3[j, "visite4"]) {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite3"] + 1
    		}
    		else {
    			toto3[j, i] <- as.integer(names(toto3)[i]) - toto3[j, "visite4"] + 1
    		}
    	}
    }
    Voyez-vous un moyen plus performant (sans passer par des boucles) pour faire ça ? Mon problème vient du fait que je doive parcourir le data frame en ligne et en colonne, et du coup je ne m'en sors pas avec une combinaison d'apply dans les 2 dimensions...

    Merci d'avance de votre aide,

    ced
    Rédacteur / Modérateur SGBD et R
    Mes tutoriels et la FAQ MySQL

    ----------------------------------------------------
    Pensez aux balises code et au tag
    Une réponse vous a plu ? N'hésitez pas à y mettre un
    Je ne réponds pas aux questions techniques par message privé, les forums sont là pour ça

  2. #2
    Membre averti
    Femme Profil pro
    Inscrit en
    Septembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France

    Informations forums :
    Inscription : Septembre 2009
    Messages : 272
    Points : 417
    Points
    417
    Par défaut
    Bonjour,
    je n'ai pas compris comment trouver la dernière date (1980 dans votre exemple):
    Mon objectif est de transformer ce data frame en un autre data frame contenant les départements en lignes, les années (de la plus ancienne du premier cycle à la plus récente du 4ème cycle), et dans chaque case le nombre d'années entre l'année de la colonne et le dernier passage dans le département (cycle le plus récent).
    Je pense néanmoins qu'il est possible d'éviter une boucle en créant un vecteur contenant les années de visite pour chaque département:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    # d: votre data.frame de départ
    dept <- sort(unique(d$dep))
    for (i in dept){
       anVis <- d$visite[d$dep==i]
    #suite à définir 
    }
    Pour la suite, il est possible de "jouer" avec ce vecteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    # dans la boucle
    L <- length(anVis)
    M <- data.frame(annee=anVis[1]:anVis[L], visite=rep(0,anVis[L]-anVis[1]+1))
    if (L==1){
      M$visite <- 1:(anVis[L]-anVis[1]+1)}
    else if (L==2){
      M$visite <- c(1:(anVis[L]-anVis[1]),1:3)}
    J'ai mis 3 parce que je n'ai vraiment pas compris comment trouver la dernière date
    Mais je pense que vous n'aurez aucun mal à finir (si ce que j'ai écrit répond à votre problème )

    J'espère vous avoir, malgré tout, donné une piste.

    Bonne continuation

Discussions similaires

  1. Eviter une double boucle
    Par Glacealeau dans le forum Langage
    Réponses: 4
    Dernier message: 24/07/2014, 10h42
  2. Sortir d'une double boucle FOR-END
    Par azboul dans le forum MATLAB
    Réponses: 4
    Dernier message: 05/12/2007, 11h07
  3. double boucle
    Par benjisan dans le forum VBA Access
    Réponses: 2
    Dernier message: 03/10/2007, 17h07
  4. [MySQL]Eviter les doubles
    Par Bouki dans le forum Requêtes
    Réponses: 5
    Dernier message: 10/10/2006, 18h15
  5. Eviter la double insertion en rafraichissant la page
    Par p0Kep0K dans le forum Langage
    Réponses: 8
    Dernier message: 08/06/2006, 14h10

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo