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 :

Problème d'utilisation de boucles FOR et IF


Sujet :

R

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Femme Profil pro
    technicien scientifique
    Inscrit en
    Juin 2019
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : technicien scientifique

    Informations forums :
    Inscription : Juin 2019
    Messages : 5
    Par défaut Problème d'utilisation de boucles FOR et IF
    Bonjour,

    Je travaille depuis plusieurs jours sur un programme et je me heurte à un problème dont je ne comprends pas l'origine…

    Je dispose d'un tableau de données répertoriant des navires en ligne et l'observation quotidienne de leur présence (codé par 1) ou absence (codé par 0) au port. Voici un extrait du DF (les 999 remplacent les NA qui me gênaient pour la suite)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    > PA [1:10, 1:10]
                Navire X01.01.2019 X02.01.2019 X03.01.2019 X04.01.2019 X05.01.2019 X06.01.2019 X07.01.2019 X08.01.2019 X09.01.2019
    1      DHANRAJIA I         999         999           0           0         999         999           0           0           0
    2           BIBINE         999         999           0           0         999         999           0           0           0
    3         THALISSA         999         999           0           0         999         999           0           0           0
    4        JULIANA 2         999         999           0           0         999         999           0           0           0
    5           JO LEA         999         999           0           0         999         999           0           0           0
    6   SAINT AMANDIER         999         999           0           0         999         999           0           0           0
    7    BLANCHE NEIGE         999           0           0           0           0           0           0           0           0
    8  MACHOIRAN BLANC         999         999           0           0         999         999           1           1           1
    9    PIMENTADE III         999         999           0           0         999         999           0           0           0
    10           DIGNA         999         999           0           0         999         999           0           0           0
    Le but de mon codage est d'obtenir la durée moyenne de sortie pour chaque bateau et de pouvoir prédire la date de retour d'un bateau qui serait sorti en ce moment (le tableau est mis à jour quotidiennement).
    Pour cela, j'ai voulu créer un nouveau tableau où je stock les dates de départ et de retour des navires grâce à un système de boucles FOR et IF.

    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
     
    # Création d'un vecteur contenant les dates d'observation (utilisable dans la boucle)
    Date <- colnames(PA[,2:ncol(PA)]) # on récupère les noms des colonnes de PA
    Date <- gsub(pattern = "X", replacement = "", Date) # On supprime le X placé devant les dates lors de l'importation des données
    Date <- as.Date(Date,"%d.%m.%y") # On convertie au format date
    Date <- Date[-which (is.na(Date)== T)] # On enlève les cellules qui n'ont pas de dates
     
    # On supprime du tableau PA les colonnes qui n'ont pas encore de données d'observation 
    PA <- PA[,1:(length(Date)+1)]
     
    # Création d'un tableau vide où s'ajouteront les noms des navires, les dates de début de marée et la durée des marées
    BatDat <- data.frame(matrix(NA, ncol = 4))
    colnames(BatDat) <- c("Navire", "Début_marée", "Fin_marée", "Durée_marée")
    z1 <- 1 # Création d'un compteur permettant de dénombrer le nombre de lignes de BatDat pour les dates de début de marée
    z2 <- 1 # Création d'un compteur permettant de dénombrer le nombre de lignes de BatDat pour les dates de fin de marée
     
    for (n in 1 : nrow(PA)){ # on parcourt les lignes du tableau 
      for(k in 3 : ncol(PA)){ # on parcourt les colonnes du tableau à partir de la 3ème, cad la seconde date pour que le k-1 soit aussi une date
         if (((PA[n,k-1] == 0) & (PA[n,k] == 1)) | ((PA[n,k-1] == 999) & (PA[n,k] == 1))) # On compare, pour un bateau donné, l'état de présence/absence afin de détecter les débuts de marée
            # print("Début de marée")
            z1 = z1 + 1 # z augmente de 1 à chauqe fois qu'une marée débute
            BatDat[z1,1] <- PA[n,1] # on stock le nom du bateau dans BatDat
            BatDat[z1,2] <- format(Date[k], "%j")  # on stock la date de début de marée dans BatDat
        }
    }
     
    for (n in 1 : nrow(PA)){ # on parcourt les lignes du tableau 
      for(k in 3 : ncol(PA)){ # on parcourt les colonnes du tableau à partir de la 3ème, cad la seconde date pour que le k-1 soit aussi une date
        if ((PA[n,k-1] == 1) & (PA[n,k] == 999) | ((PA[n,k-1] == 1) & (PA[n,k] == 0))) # On compare, pour un bateau donné, l'état de présence/absence afin de détecter les débuts de marée
          z2 = z2 + 1 # z augmente de 1 à chauqe fois qu'une marée finit
          # print("Fin de marée")
        BatDat[z2,3] <- format(Date[k], "%j") # on stock le nom du bateau et la date de début de marée dans un tableau
      } 
    }
    Pour résumer : je compare les cellules 2 à 2 de façon à trouver les premiers 1 et les derniers 1 de chaque série et à extraire les dates correspondantes.
    Dans l'idée, mon code marche plutôt bien.

    Le problème c'est que, quand il arrive au bout d'une ligne, il compare la dernière cellule avec la première cellule de la ligne suivante, ce qui fausse totalement l'extraction des dates…
    Par exemple, avec l'extrait fourni : pour le navire "Machoiran blanc", j'obtiens une date de départ le 07/01/2019 et en date de retour le 01/01/2019. Bref, il est rentré avant de sortir ! (Ils sont forts, ces pêcheurs !)

    Voilà, si quelqu'un à une idée pour régler ce problème, je suis preneuse ! Ou, éventuellement, une façon plus élégante de faire l'extraction des dates…
    J'ai essayé d'insérer la fonction "next" dans mon code mais ça n'a rien donné. J'ai également essayé de voir pour appliquer des fonctions de type "ifelse" ou "apply" mais je vois pas trop comment elles peuvent résoudre mon problème…

    Merci !

  2. #2
    Expert confirmé
    Avatar de olivier.decourt
    Homme Profil pro
    Formateur R/SAS/statistiques
    Inscrit en
    Avril 2008
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Formateur R/SAS/statistiques
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Par défaut
    Bonjour Tiphaine.
    Je vais plutôt te proposer une autre façon de faire, en plusieurs étapes.
    1) transformer tes données pour avoir une ligne par couple (bateau, date) avec une fonction comme reshape2::melt ou tidyr::gather
    2) sur cette nouvelle organisation des données, filtrer les lignes avec des valeurs 1
    3) toujours sur ces données, filtrées, transformer le nom des anciennes colonnes en vraies dates (comme tu le fais actuellement avant la boucle)
    4) récupérer pour chaque bateau la date min et la date max avec dplyr::group_by et dply::summarise par exemple.

  3. #3
    Futur Membre du Club
    Femme Profil pro
    technicien scientifique
    Inscrit en
    Juin 2019
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : technicien scientifique

    Informations forums :
    Inscription : Juin 2019
    Messages : 5
    Par défaut
    J'ai réussi à contourner le problème en rajoutant une colonne vide à la fin de mon dataframe PA mais c'est vraiment du bidouillage et ça me plait moyennement…

    J'essaie votre solution mais je ne connais aucune des fonctions que vous proposez alors ça prend un peu de temps ^^'
    Merci pour votre réponse en tout cas ! =)

  4. #4
    Futur Membre du Club
    Femme Profil pro
    technicien scientifique
    Inscrit en
    Juin 2019
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : technicien scientifique

    Informations forums :
    Inscription : Juin 2019
    Messages : 5
    Par défaut
    Bonjour Olivier,

    J'ai appliqué la méthode que vous me proposez sans problème jusqu'à l'étape 3 incluse !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    # Transformation de PA en un tableau en longueur, ie une ligne par date
    library("reshape2")
    long <- melt(data = PA) # On crée le nouveau tableau
    colnames(long) <- c("Navires", "Date", "Presence") # On renomme les colonnes
    library("lubridate")
    long$Date <- dmy(gsub(pattern = "X", replacement = "", long$Date)) # On enlève le X devant chaque date et on transforme le date
    long$Date <- as.Date(long$Date, "%y-%m-%d") # On converti au format date
    long <- long[!is.na(long$Date) == T, ] # On supprime les lignes qui n'ont pas de dates et qui correspondent aux colonnes non remplies de PA
     
    library(dplyr)
    Pres <- filter(long, Presence == 1) #; On filtre les lignes n'ayant que des 1, cad les navires présents et les dates auxquelles ils le sont.
    J'obtiens donc mon tableau "Pres" qui stock toutes les dates où les navires ont été présents au port. Jusque là, tout va bien !

    Il reste donc la 4ème étape et là, je rencontre des difficultés : je ne vois pas du tout comment utiliser group_by et summarise pour récupérer les données dont j'ai besoin, à savoir : la durée moyenne des sorties pour chaque navire et savoir si un navire "X" est actuellement sortit et depuis combien de jours (la comparaison de ce nombre de jours avec la durée moyenne donnant une estimation de son jour de retour, ce que je recherche! ).

    Pouvez-vous encore m'aider svp ? ^^'

    Merci beaucoup !

    Tiphaine

  5. #5
    Expert confirmé
    Avatar de olivier.decourt
    Homme Profil pro
    Formateur R/SAS/statistiques
    Inscrit en
    Avril 2008
    Messages
    2 064
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France

    Informations professionnelles :
    Activité : Formateur R/SAS/statistiques
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Par défaut
    Bonjour Tiphaine.
    Bravo, vous y êtes presque !
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    durees <- Pres %>%
                               group_by(Navires) %>%
                               summarise(depart = min(Date),
                                              retour = max(Date)) %>%
                             mutate(duree = as.integer(retour-depart))
    Est-ce que le résultat correspond à ce que vous cherchez ?

  6. #6
    Futur Membre du Club
    Femme Profil pro
    technicien scientifique
    Inscrit en
    Juin 2019
    Messages
    5
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : technicien scientifique

    Informations forums :
    Inscription : Juin 2019
    Messages : 5
    Par défaut
    Malheureusement non…. ^^'
    J'étais arrivée à ce résultat aussi (avec un code différent) mais ça donne la durée totale passée en mer. Or ce que j'aimerais, c'est la durée pour chaque sortie.

    Par exemple :
    Le bateau Bibine sort une première fois entre le 14/01/2019 et le 22/01/2019 soit 9 jours, puis il ressort entre le 29/01/2019 et le 07/02/2019 soit 10 jours et ainsi de suite jusqu'à la dernière date. Une fois qu'on a la durée de chaque sortie de ce bateau, on peut faire une moyenne.
    Il me faudrait également un moyen d'isoler la dernière sortie du navire SI il n'est pas encore rentrer au port (donc la dernière observation qu'on a est un 1) de façon à comparer le nombre de jours qu'il a déjà passé en mer avec la moyenne calculée précédemment et comme ça, on peut estimer sa date de retour au port. (Pour cette partie j'avais déjà réussi à bidouiller un code à la suite de mes boucles car j'avais pu isoler dans 2 colonnes les dates de sorties et de retours de chaque bateau).

    Je sais pas si je suis très claire donc hésitez pas à me demander plus de précision ^^'

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilisation des boucles for
    Par _Michel dans le forum Débuter
    Réponses: 6
    Dernier message: 23/09/2008, 11h49
  2. utiliser une boucle 'for' in JAsperReport
    Par Javix dans le forum Jasper
    Réponses: 6
    Dernier message: 13/12/2007, 10h05
  3. [Tableaux] Utiliser une boucle for dans un echo
    Par maoboy dans le forum Langage
    Réponses: 7
    Dernier message: 18/06/2007, 13h55
  4. [FLASH 8] Problème nom variable et boucle for
    Par jbidou88 dans le forum Flash
    Réponses: 10
    Dernier message: 23/03/2007, 11h36
  5. [VB6] Problème contrôle Timer et boucle For-Next ...
    Par Stéphane BEHMENBURG dans le forum VB 6 et antérieur
    Réponses: 6
    Dernier message: 01/12/2005, 17h36

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