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

SAS Base Discussion :

Comment dupliquer des lignes sous conditions


Sujet :

SAS Base

  1. #1
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut Comment dupliquer des lignes sous conditions
    Bonjour,

    J'ai une table ou la clef c'est le NumEtudiant.
    C'est une table de 5 colonnes en tout.

    Avec un exemple c'est plus facile à comprendre:

    J'ai cette table

    NumEtudiant DateDebut Note Coefficent Groupe
    001254 201703 17 2 S
    001254 201707 16 1 I
    001478 201706 15 2 I
    001478 201707 14 3 I

    Je souhaite pour chaque NumEtudiant si l'info n'existe pas pour un mois, reprendre la ligne du mois précédent la dupliquer, de sorte à ce que à la fin j'ai pour chaque NumEtudiant

    Je souhaite avoir ca à la fin, cette table:

    NumEtudiant DateDebut Note Coefficent Groupe
    001254 201703 17 2 S
    001254 201704 17 2 S
    001254 201705 17 2 S
    001254 201706 17 2 S
    001254 201707 16 1 I
    001478 201706 15 2 I
    001478 201707 14 3 I

    Pour le NumEtudiant 001254, on avait pas de ligne pour les mois de 201704, 201705 et 201706 : on duplique la ligne de 201703 pour ces 3 mois.

    Si vous pouvez m'aider ca m'aidrait à terminer mon stage

    Merci d'avance,

    Meryem

  2. #2
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Comment dupliquer des lignes sous conditions
    Bonjour,

    Vous pouvez regarder ce message.

    Cordialement,

  3. #3
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Merci pour cette réponse rapide.

    Mais j'ai 2 colonnes clefs : NumEtudiant et DateDebut.

    Dans ce message il y en a une seul : x.

    et mes dates DateDebut, ca va pas de 1 en 1 (de 201704 à 201705 effectivement on a un pas de 1, mais de 201612 à 201701 par exemple non).

    Donc c'est un peu plus compliqué mais j'essaye de l'adapter.

    Et les NumEtudiant c'est pas des 1, 2, 3... mais 07089932, 00541434...

  4. #4
    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 : 46
    Localisation : France

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

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Points : 4 478
    Points
    4 478
    Par défaut
    Bonjour.
    Une solution possible :
    1. créer une table avec une ligne par étudiant, et trois colonnes (identifiant, mois le plus ancien, mois le plus récent), en SQL par exemple, ou avec une proc MEANS
    2. avec une étape Data, générer tous les mois dans cet intervalle pour chaque étudiant, avec une boucle DO et une instruction OUTPUT ==> on obtient un "squelette" complet
    3. fusionner avec les vraies données
    4. parcourir le résultat de la jointure en reprenant les valeurs de l'observation précédente si elles sont manquantes (= pour les mois absents des données), avec une fonction LAG (attention à ne jamais utiliser LAG après un IF ou un ELSE)

    Deux remarques : 1) ça sera plus simple si tu crées les mois en dates SAS, une fonction avec INTNX permettant d'ajouter aisément des mois ; 2) on peut probablement tout faire en une seule étape mais le code risque d'être assez moche, long et peu maintenable. L'algorithme ci-dessus offre au moins la possibilité de contrôler les résultats intermédiaires.
    Bon courage.
    Olivier

  5. #5
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Merci Olivier pour ta proposition mais peu compliqué pour moi j'avoue je ne suis pas experte en SAS.

    je ne vais travailler que sur 2017 pour faire plus simple (la periode 201701-201707 est celle qui m'intérèsse le plus).

    et là j'ai des pas de 1 en 1 pour DateDebut, d'un mois à l'autre (entre 201701 et 201707).

    et ca me rapproche de la discussion que mgdondon m'a demandé de regarder : avec 2 différences maintenant ( 1) les NumEtudiant ne sont pas des pas de 1 en 1, le plus simple serait d'attribuer un chiffre à chaque étudiant (j'ai 20874 etudiants donc 20874 NumEtudiant différents et 2) ensuite faire une double boucle )

    Parce que là pour mes 2 variables clefs NumEtudiant et DateDebut, j'aurai des pas de 1 en 1.

    Meryem

  6. #6
    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 : 46
    Localisation : France

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

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 064
    Points : 4 478
    Points
    4 478
    Par défaut
    Bonjour Meryem.
    Dans la solution de mgdondon, il faut bien garder à l'esprit que tu n'as pas forcément besoin d'écrire 2 boucles, puisque SET est déjà une boucle (qui itère sur les observations d'une table).
    Cela dit, le code qui correspond me semble un peu galère à écrire, puisqu'à chaque observation il faudra vérifier que le mois courant est bien la suite immédiate du mois à l'observation précédente (avec un LAG par exemple), et si ce n'est pas le cas, lancer une boucle pour boucher les trous. Pourquoi pas, le code fera une dizaine de lignes mais ne sera pas forcément simple à comprendre.
    As-tu essayé l'enchaînement que je proposais ? Si oui, à quelle étape butes-tu ? Si tu ne proposes pas de code, on a l'impression de devoir bosser à ta place...
    Bon courage.
    Olivier

  7. #7
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Comment dupliquer des lignes sous conditions
    Bonjour,

    Les deux propositions reposent sur le même principe : la première étape consiste à créer les lignes manquantes et la deuxième à remplacer les données manquantes par les valeurs précédentes.

    Olivier décompose l'étape 1 pour vos données (points 1, 2, 3). Le point 4 correspond à l'étape 2 en utilisant l'instruction lag plutôt qu'un double set.

    Cordialement,

  8. #8
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    data table1;
    set TableEtudiants(where=((input(substr(DATDEB, 1, 6), 6.)) >= 201701));
    NumEtudiant1=input(substr(NumEtudiant, 1, 6), 6.);
    DATDEB1 = input(substr(DATDEB, 1, 6), 6.);
    run;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    proc sort data=table1;
    by NumEtudiant1 DATDEB1 ;
    run;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    data table2;
      do NumEtudiant1 = 00000033 to 90908761  ;
         do DATDEB1=201701 to 201707;
        output;
    	end;
    	output;
      end;
    run;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    data table;
      merge table1 table2;
      by NumEtudiant1 DATDEB1;
    run;

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    data table3;
      set table;
      n=_n_;
      if missing(Note ) then do;
         do until (not missing(Note ));
           n=n-1;
           set table(keep=Note Coefficent Groupe) point=n;
         end;
      end;
    run;

  9. #9
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Voilà mon code car je n'arrive pas à utiliser la méthode d'Olivier, trop compliqué pour moi de la faire seule.

    Mais le pb je pense que c'est que NumEtudiant1 ne va pas de 1 à N (N= nb d'étudiants) : avec des pas de 1 en 1.

    J'essaye d'abord de trouver comment créer une autre colonne NumEtudiant2 ou j'ai 1, 2,.....N : après sûrement la double boucle marchera bien.

    Merci encore pour votre aide

  10. #10
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Pour répondre à votre question Olivier sur votre méthode : j'avais réussi à faire que la 1ère étape et avec une autre méthode (je n'ai pas réussi avec la solution proposé)

    Voila l'étape 1 avec ma méthode:

    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
    data table_OLDEST_DATEDEB1(rename=(DATDEB1=OLDEST_DATEDEB1));
    set TableEtudiants;
    NumEtudiant1=input(substr(NumEtudiant, 1, 6), 6.);
    DATDEB1 = input(substr(DATDEB, 1, 6), 6.);
    run;
    proc sort data=table_OLDEST_DATEDEB1(keep=NumEtudiant1 OLDEST_DATEDEB1) ;
    by NumEtudiant1 OLDEST_DATEDEB1;
    run;
    proc sort data=table_OLDEST_DATEDEB1 nodupkey;
    by NumEtudiant1 ;
    run;
     
    data table_YOUNGEST_DATEDEB1(rename=(DATDEB1=YOUNGEST_DATEDEB1));
    set TableEtudiants;
    NumEtudiant1 =input(substr(NumEtudiant, 1, 6), 6.);
    DATDEB1 = input(substr(DATDEB, 1, 6), 6.);
    run;
     
    proc sort data=table_YOUNGEST_DATEDEB1(keep=NumEtudiant1 YOUNGEST_DATEDEB1);
    by NumEtudiant1 descending YOUNGEST_DATEDEB1;
    run;
    proc sort data=table_YOUNGEST_DATEDEB1 nodupkey;
    by NumEtudiant1 ;
    run;
     
    data table;
      merge table_OLDEST_DATEDEB1 YOUNGEST_DATEDEB1;
      by NumEtudiant1 ;
    run;

  11. #11
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    L'étape : avec une étape Data, générer tous les mois dans cet intervalle pour chaque étudiant, avec une boucle DO et une instruction OUTPUT.

    Pour cette étape je ne vois pas comment faire? surtout que une boucle do, ca marche si on a des pas de en 1.
    donc e 201701 à 201702 : ok ca marche
    Mais
    après 201612 si je fais un pas de 1 on a 201613 (alors que après 201612 décembre 2016, on a 201701 janvier 2017).

  12. #12
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Comment dupliquer des lignes sous conditions
    Bonjour,

    Il faut aussi prendre en compte la remarque associée :

    Citation Envoyé par olivier.decourt Voir le message
    1) ça sera plus simple si tu crées les mois en dates SAS, une fonction avec INTNX permettant d'ajouter aisément des mois ;
    Cordialement,

    PS : Pensez à utiliser les balises [CODE] autour de votre code, ça facilite la lecture.
    Nom : Sans titre.jpg
Affichages : 2556
Taille : 3,9 Ko

  13. #13
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Je n'y arrive toujours pas, c'est trop compliqué pour moi l'étape 2 proposé par Olivier.

    J'ai trouvé une méthode plus simple pour moi:

    Je vais le faire en 2 fois : une fois en 2017 (de 201701 à 201707) puis en 2016 (de 201601 à 201612):
    ensuite je ferai un set.

    Pour 2017 : 1) Je créer une table ou au final j'ai pour chaque NumEtudiant 7 lignes (201701...201707)
    2) je merge avec les vraies données
    3) je remplace les valeurs manquantes avec le set proposé par mgdondon qui

    J'ai réussi l'étape 1 avec le code suivant:

    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
    data table1(keep=NumEtudiant) ;
    set TableEtudiants;
    NumEtudiant1=input(substr(NumEtudiant, 1, 8), 8.);*/
    run;
     
    proc sort data=table1 nodupkey;
    by NumEtudiant1;
    run;
     
    data table2;
    set table1;
    date1 = 201701;
    date2 = 201702;
    date3 = 201703;
    date4 = 201704;
    date5 = 201705;
    date6 = 201706;
    date7 = 201707;
    run;
     
    PROC TRANSPOSE DATA=work.table2 OUT=work.tables3 ;
    	BY NumEtudiant;
    	VAR date1 date2 date3 date4 date5 date6 date7 ;
    RUN ;
    L'étape 2 le merge est simple ca aussi j'ai réussi.

    Je bloque que sur l'étape 3

    Meryem

  14. #14
    Membre expérimenté
    Homme Profil pro
    Attaché statisticien
    Inscrit en
    Mai 2011
    Messages
    687
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Attaché statisticien
    Secteur : Administration - Collectivité locale

    Informations forums :
    Inscription : Mai 2011
    Messages : 687
    Points : 1 581
    Points
    1 581
    Par défaut
    Bonjour.

    Je reformule ton problème.

    Tu as une table d'individu/périodes : i.e. individu/periode=(NumEtudiant,DateDebut)

    Tu n'as dans tes données qu'une seule ligne au plus par individu période

    Pour chaque individu tu souhaite obtenir une table finale avec tous les individu/periode de chaque individu entre son premier individu/periode et son dernier individu/periode

    Si un individu/periode est manquant alors tu le créé à partir des données de l'individu période précédent

    Ta table en entrée est triée par individus/periode


    L'incrément différent de 1 de ta période que tu soulève comme un problème est un faux problème : En effet ta période n'est qu'une renumérotation d'un sous ensemble de l'ensemble des entiers , et de même que N peut-être être entièrement défini de façon simple par la définition du successeur de chacun de ses éléments, de même peux-tu définir ta période/renumérotation de N par définiton du successeur de chacun de ses éléments

    Ensuite l'algorithme est simple il te suffit de l'énoncer litteralement


    Algorithme

    1 - Lire Ligne (itérateur SAS)
    2 - Si Ligne est la premiere ligne d'un individu alors Faire (a)
                                PeriodeCourante=Periode
                                Output
                                   FinFaire (a)
        Sinon     Faire (b) Si Successeur(PeriodeCourante)=Periode alors Faire (c)
                                        PeriodeCourante=Periode
                                        Output
                                           FinFaire (c)
            
            Sinon     Faire (d)
                PeriodeCible=Periode 
                        /* on va combler les trous de PeriodeCourante jusqu'à PeriodeCible-1 */
                Recharger le vecteur de la période antérieure (i.e. Periode=PeriodeCourante)
                    Faire (e) tant que Successeur(Periode)^=PeriodeCible
                    Periode=Successeur(Periode)
                    Output
                    FinFaire (e)
                        /* et on fini par PeriodeCible
                Recharge le vecteur pour Periode=PeriodeCible
                PeriodeCourante=Periode
                Output
                FinFaire (d)
            FinFaire (b)


    Pour revenir au code SAS

    L'aspect le plus délicat est la création de la fonction successeur j'ai fait le choix d'utiliser une FMCP par exemple, mais on peut tout aussi bien la coder en étape DATA ce qui améliorerait les performances. Cependant par choix didactique la séparation offerte par la FMCP permet d'isoler les deux parties du problème.
    A noter la séparation aurait pu se faire aussi bien par recours au macrocode.

    L'algorithme du successeur de la periode est simple : lorsqu'on arrive à 12 , on rajoute une année et on revient à 01, sinon on incrémente d'1

    Pour le reste du code, la mémoire est simulée par un tableau associatif (HASH) , ce qui au delà de lourdeur de la syntaxe de déclaration du HASH permet une certaine élégance dans la mise en oeuvre ce qui permet au code de garder l'esprit de l'algorithme.

    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
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
     
     
    DATA JeuDeTest;
    INFILE DATALINES;
    LENGTH NumEtudiant $6 Periode $6 Note 8 Coefficent 8 Groupe $1 ;
    INPUT 
    NumEtudiant  Periode  Note Coefficent  Groupe  ;
    DATALINES;
    001254 201703 17 2 S
    001254 201707 16 1 I
    001478 201706 15 2 I
    001478 201707 14 3 I
    007777 201606 11 2 I
    007777 201707 14 3 S
    007777 201801 19 5 I
    ;
    RUN;
     
     
     
     /** definition de la fonction periode suivante d un periode **/
     
    PROC FCMP OUTLIB=work.funcs.temp ;
    FUNCTION PeriodeSuivante(periode $) $;
    mois=SUBSTR(periode,5,2);
    annee=SUBSTR(periode,1,4);
    nummois=INPUT(mois,8.)+1;
    numannee=INPUT(annee,8.);
    IF nummois=13     THEN         DO;
                                nummois=1;
                                IncAnnee=1;
                                END; 
                    ELSE IncAnnee=0;
    numannee=numannee+IncAnnee;
    successeur=PUT(numannee,z4.)!!PUT(nummois,z2.);
        RETURN (successeur);
    ENDSUB;
    QUIT;
     
    /** decl de la librairie de fonctions **/
     
    OPTIONS CMPLIB=work.funcs;
     
    /** Liste des variables de la table en entree **/
     
    %MACRO ListeVar(DATA=,VarSortie=);
     
    %GLOBAL &VarSortie;
     
    PROC CONTENTS  DATA = &DATA NOPRINT
              OUT = file (KEEP = name );
    RUN;
     
    PROC SQL NOPRINT; 
    SELECT DISTINCT name 
    INTO: &VarSortie SEPARATED BY ","
    FROM file; 
    QUIT; 
    %MEND;
     
    %ListeVar(DATA=JeuDeTest,VarSortie=Liste);
     
    DATA _null_;
    CALL SYMPUT ('BListe',TRANWRD("&Liste",","," "));
    CALL SYMPUT ('QListe',"'"!!TRANWRD("&Liste",",","','")!!"'");
    RUN;
     
     
     
    /**** mise en oeuvre de l algorithme ****/
     
    DATA Resultat;
    LENGTH TypePeriode $10 ;
    IF 0 THEN SET JeuDeTest; /** declaration type et taille des variables nécessaire pour la definition du Hash **/
    IF _N_=1 THEN   DO;
                        DECLARE HASH MEMOIRE();
                        MEMOIRE.DEFINEKEY('TypePeriode');
                        MEMOIRE.DEFINEDATA('TypePeriode',&QListe);
                        MEMOIRE.DEFINEDONE();
                    END;
    RETAIN PeriodeCourante ;
    SET JeuDeTest;
    BY NumEtudiant periode;
     
    IF FIRST.NumEtudiant       THEN DO;
                    RCM=MEMOIRE.CLEAR();
                    PeriodeCourante=Periode;
                    TypePeriode="Courante";
                    OUTPUT;
                    RCM=MEMOIRE.ADD();
                                    END;
     
        ELSE DO;
        IF PeriodeSuivante(PeriodeCourante)=Periode    
            THEN    DO;
                            RCM=MEMOIRE.CLEAR();
                            PeriodeCourante=Periode;
                            TypePeriode="Courante";
                            OUTPUT;
                            RCM=MEMOIRE.ADD();
                    END;
            ELSE    DO;
                        PeriodeCible=Periode;
                        TypePeriode="Cible";
                        RCM=MEMOIRE.ADD();
                        TypePeriode="Courante";
                        RCM=MEMOIRE.FIND();
                        *Periode=PeriodeSuivante(Periode);
                        DO UNTIL (PeriodeSuivante(Periode)=PeriodeCible);
                        Periode=PeriodeSuivante(Periode);
                        OUTPUT;
                        END;
                        TypePeriode="Cible";
                        RCM=MEMOIRE.FIND();
                        RCM=MEMOIRE.CLEAR();
                        TypePeriode="Courante";
                        RCM=MEMOIRE.ADD();
                        OUTPUT;
                    END;
     
        END;
     
    KEEP &BListe;
    RUN;

    Jeu de Test

    Obs. NumEtudiant Periode Note Coefficent Groupe
    1 001254 201703 17 2 S
    2 001254 201707 16 1 I
    3 001478 201706 15 2 I
    4 001478 201707 14 3 I
    5 007777 201606 11 2 I
    6 007777 201707 14 3 S
    7 007777 201801 19 5 I

    Resultat

    Obs. NumEtudiant Periode Note Coefficent Groupe
    1 001254 201703 17 2 S
    2 001254 201704 17 2 S
    3 001254 201705 17 2 S
    4 001254 201706 17 2 S
    5 001254 201707 16 1 I
    6 001478 201706 15 2 I
    7 001478 201707 14 3 I
    8 007777 201606 11 2 I
    9 007777 201607 11 2 I
    10 007777 201608 11 2 I
    11 007777 201609 11 2 I
    12 007777 201610 11 2 I
    13 007777 201611 11 2 I
    14 007777 201612 11 2 I
    15 007777 201701 11 2 I
    16 007777 201702 11 2 I
    17 007777 201703 11 2 I
    18 007777 201704 11 2 I
    19 007777 201705 11 2 I
    20 007777 201706 11 2 I
    21 007777 201707 14 3 S
    22 007777 201708 14 3 S
    23 007777 201709 14 3 S
    24 007777 201710 14 3 S
    25 007777 201711 14 3 S
    26 007777 201712 14 3 S
    27 007777 201801 19 5 I

    Edit : J'ai remplacé ta variable DateDebut par la variable Periode, je te laisse adapter au besoin.

  15. #15
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Comment dupliquer des lignes sous conditions
    Bonjour,

    Avec l'algorithme d'Olivier :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    data test;
      input NumEtudiant :$6. DateDebut :yymmn6. Note Coefficent Groupe :$1.;
      format DateDebut yymmn6.;
      cards;
    001254 201703 17 2 S
    001254 201707 16 1 I
    001478 201706 15 2 I
    001478 201707 14 3 I
    007777 201606 11 2 I
    007777 201707 14 3 S
    007777 201801 19 5 I
    ;
    run;

    • créer une table avec une ligne par étudiant, et trois colonnes (identifiant, mois le plus ancien, mois le plus récent), en SQL par exemple, ou avec une proc MEANS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    proc sql;
      create table periode as
        select NumEtudiant, min(DateDebut) as DateMin, max(DateDebut) as DateMax
        from test
        group by NumEtudiant;
     
    data periode;
      set periode;
      format DateMin DateMax yymmn6.;
    run;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
                                           Num         Date      Date
                                         Etudiant       Min       Max
                                          001254     201703    201707
                                          001478     201706    201707
                                          007777     201606    201801

    • avec une étape Data, générer tous les mois dans cet intervalle pour chaque étudiant, avec une boucle DO et une instruction OUTPUT ==> on obtient un "squelette" complet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    data periode(keep=NumEtudiant DateDebut);
      set periode;
      by NumEtudiant;
      if first.NumEtudiant then DateDebut=DateMin;
      do while (DateDebut <= DateMax);
        output;
        DateDebut = intnx('month', DateDebut, 1);
      end;
    run;
    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
                                                Num         Date
                                              Etudiant     Debut
                                               001254     201703
                                               001254     201704
                                               001254     201705
                                               001254     201706
                                               001254     201707
                                               001478     201706
                                               001478     201707
                                               007777     201606
                                               007777     201607
                                               007777     201608
                                               007777     201609
                                               007777     201610
                                               007777     201611
                                               007777     201612
                                               007777     201701
                                               007777     201702
                                               007777     201703
                                               007777     201704
                                               007777     201705
                                               007777     201706
                                               007777     201707
                                               007777     201708
                                               007777     201709
                                               007777     201710
                                               007777     201711
                                               007777     201712
                                               007777     201801

    • fusionner avec les vraies données
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    data test;
      merge test periode;
      by NumEtudiant DateDebut;
    run;
    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
                                Num         Date
                              Etudiant     Debut    Note    Coefficent    Groupe
                               001254     201703     17          2          S
                               001254     201704      .          .
                               001254     201705      .          .
                               001254     201706      .          .
                               001254     201707     16          1          I
                               001478     201706     15          2          I
                               001478     201707     14          3          I
                               007777     201606     11          2          I
                               007777     201607      .          .
                               007777     201608      .          .
                               007777     201609      .          .
                               007777     201610      .          .
                               007777     201611      .          .
                               007777     201612      .          .
                               007777     201701      .          .
                               007777     201702      .          .
                               007777     201703      .          .
                               007777     201704      .          .
                               007777     201705      .          .
                               007777     201706      .          .
                               007777     201707     14          3          S
                               007777     201708      .          .
                               007777     201709      .          .
                               007777     201710      .          .
                               007777     201711      .          .
                               007777     201712      .          .
                               007777     201801     19          5          I

    • parcourir le résultat de la jointure en reprenant les valeurs de l'observation précédente si elles sont manquantes (= pour les mois absents des données)
    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
    data test;
      set test;
      retain new_Note new_Coefficent new_Groupe;
      if not(missing(Note)) then do;
        new_Note=Note;
        new_Coefficent=Coefficent;
        new_Groupe=Groupe;
      end;
      else do;
        Note=new_Note;
        Coefficent=new_Coefficent;
        Groupe=new_Groupe;
      end;
      drop new_Note new_Coefficent new_Groupe;   
    run;
    Cordialement,

  16. #16
    Membre expérimenté
    Homme Profil pro
    Développeur en SAS/ Statisticien
    Inscrit en
    Janvier 2013
    Messages
    483
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : Développeur en SAS/ Statisticien
    Secteur : Enseignement

    Informations forums :
    Inscription : Janvier 2013
    Messages : 483
    Points : 1 552
    Points
    1 552
    Par défaut
    Bonjour,
    Si j'ai bien compris une étape data suffit pour résoudre ce problème. Voici la proposition :
    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
    data Test ;
    input NumEtud DateDebut $ Note Coefficent Groupe $ ;
    DateDeb=input(DateDebut, yymmn6.) ;
    DATALINES;
    001254 201703 17 2 S
    001254 201707 16 1 I
    001478 201706 15 2 I
    001478 201707 14 3 I
    007777 201606 11 2 I
    007777 201707 14 3 S
    007777 201801 19 5 I
    ; run ; 
     
    data Final ;
    merge Test Test( keep=NumEtud DateDeb 
                     rename=(NumEtud=_NumEtud DateDeb=_DateDeb) firstobs=2 ) ;
    output;
     
    if NumEtud=_NumEtud then 
    do;
      	Temp=DateDeb ;
      	do i=1 to intck('month', Temp, _DateDeb)-1  ;
        		DateDeb=intnx('month', Temp, i) ; 
    		output ;
    	end;
    end;
    drop i Temp _: ;
    format DateDeb yymmn6. ; 
    run ;
    La base devrait être triée au préalable par NumEtud.

    Cordialement Ward

  17. #17
    Membre expérimenté
    Inscrit en
    Novembre 2009
    Messages
    703
    Détails du profil
    Informations forums :
    Inscription : Novembre 2009
    Messages : 703
    Points : 1 311
    Points
    1 311
    Par défaut Comment dupliquer des lignes sous conditions
    Ça marche parfaitement, très sioux.

    Cordialement,

  18. #18
    Candidat au Club
    Femme Profil pro
    Étudiant
    Inscrit en
    Août 2017
    Messages
    9
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Val d'Oise (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Août 2017
    Messages : 9
    Points : 3
    Points
    3
    Par défaut
    Mille merci à vous 4, Olivier, hossward, JeromeMathias et mgdondon

    La méthode d'hossward est magique.

    Et si je veux que pour tous mes NumEtud ca va et que ca s'arrête jusqu'à aujourd'hui c'est à dire 201708, est-ce possible avec cette méthode? (J'essaye mais je n'y arrive pas encore).

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

Discussions similaires

  1. Dupliquer des lignes sous conditions
    Par bomimi dans le forum Excel
    Réponses: 3
    Dernier message: 14/07/2015, 10h46
  2. [XL-2003] déplacement des lignes sous conditions
    Par tazko dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/03/2011, 19h57
  3. Masquer des lignes sous condition
    Par linousxm dans le forum Macros et VBA Excel
    Réponses: 4
    Dernier message: 23/05/2010, 13h19
  4. copier des lignes sous conditions (dans 2 colonnes différentes)
    Par olive08 dans le forum Macros et VBA Excel
    Réponses: 18
    Dernier message: 12/10/2007, 14h44
  5. Suppression des lignes sous condition multiple
    Par baptbapt dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 20/06/2007, 16h23

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