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 :

Condition sur un sous-ensemble d'observations


Sujet :

SAS Base

  1. #1
    Futur Membre du Club
    Condition sur un sous-ensemble d'observations
    Bonjour,
    Je souhaiterais travailler sur un sous-ensemble d'observations, c'est-à-dire par identifiant. Je m'explique:


    [TH]ID[/TH]
    [TH]BLOC[/TH]
    [TH]STATUT[/TH]
    1 1 1
    1 2 3
    1 3 2
    2 1 1
    3 1 1
    3 2 1

    Mon code:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DATA matable;
    SET matable;
    IF BLOC = 1 and STATUT = 1 then STATUT2 = "en cours";
    run;


    Je souhaiterais obtenir :


    [TH]ID[/TH]
    [TH]BLOC[/TH]
    [TH]STATUT[/TH]
    [TH]STATUT2[/TH]
    1 1 1 "en cours"
    1 2 3 "en cours"
    1 3 2 "en cours"
    2 1 1
    3 1 1
    3 2 1

    Or pour l'instant, "en cours" ne s'affiche que sur la première ligne.

    Merci,
    Garpe

  2. #2
    Membre éprouvé
    Etape data
    Bonjour,

    Votre code fonctionne correctement :

    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
    data matable;
      input id bloc statut;
      cards;
    1 	1 	1
    1 	2 	3
    1 	3 	2
    2 	1 	1
    3 	1 	1
    3 	2 	1
    ;
    run;
     
    data matable;
      set matable;
      if bloc=1 and statut=1 then statut2="en cours";
    run;


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    id    bloc    statut    statut2
     1      1        1      en cours
     1      2        3
     1      3        2
     2      1        1      en cours
     3      1        1      en cours
     3      2        1


    Cordialement,

  3. #3
    Futur Membre du Club
    Bonjour, merci pour votre réponse. Je me suis peut-être mal exprimée, en fait je souhaiterais que "en cours" s'affiche pour toutes les lignes de l'individu 1 : c'est-à-dire que si l'individu 1 a le statut 1 pour le bloc 1 alors statut2 vaut "en cours" pour tous ses blocs (1, 2 et 3). Ce qui n'est pas le cas actuellement...

    Bien à vous,
    Garpe

  4. #4
    Membre éprouvé
    merge
    Pardon, j'ai lu trop vite.

    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
    data matable;
      input id bloc statut;
      cards;
    1 1 1
    1 2 3
    1 3 2
    2 1 1
    3 1 1
    3 2 1
    ;
    run;
     
    data statut2(keep=id statut2);
      set matable;
      if id=1 and bloc=1 and statut=1;
      statut2="en cours";
    run;
     
    data matable;
      merge matable statut2;
      by ID;
    run;


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    id    bloc    statut    statut2
     1      1        1      en cours
     1      2        3      en cours
     1      3        2      en cours
     2      1        1
     3      1        1
     3      2        1


    Cordialement,

  5. #5
    Futur Membre du Club
    Merci pour votre rapidité! Désolée, ça ne fonctionne pas sur mes données car j'avais simplifié le problème. Je ne l'ai pas précisé mais cette condition fait partie d'une sous-condition: voici mon "vrai" code:

    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
    data matable;
      input ID BLOC STATUT;
      cards;
    1 	1 	1
    1 	2 	2
    1 	3 	4
    2 	1 	1
    2      2       4
    2      3       1
    3 	1 	1
    3 	2 	1
    3      3       2
    ;
    run;
     
    PROC SORT data = matable;
    By ID descending BLOC;
    run;
     
    DATA matable;
    SET matable;
    by ID;
    IF BLOC= 1 and Statut= 4  then statut_prov = "A FAIRE"; 
    IF BLOC= 1 and Statut^= 4 then statut_prov = "EN COURS";
    IF first.ID and BLOC= 3 and Statut= 1 then statut2= "EN COURS";
    IF first.ID and BLOC= 3 and Statut= 2 then statut2= "A VALIDER";
    IF first.ID and BLOC= 3 and Statut= 4 then statut2 = statut_prov;
    RUN;


    (en français cela donne: pour un individu i, si bloc = 3 et statut = 4 et si bloc = 1 et statut = 4 alors statut2 = "à faire", sinon statut2 = "en cours")

    Avec votre proposition, d'après ce que j'ai testé, "en cours" écrase tous les statut2 déjà attribués (càd par exemple les personnes qui auraient bloc = 3 et statut = 2 mais bloc = 1 et statut = 1: normalement elles devraient avoir statut2 = "à valider" et non "en cours")

  6. #6
    Membre éprouvé
    étape data
    Ce qui ce conçoit bien s'énonce clairement... c'est la première étape pour programmer quoi que ce soit...

    si (bloc = 3 et statut = 4) OU si (bloc = 1 et statut = 4) alors statut2 = "à faire", sinon statut2 = "en cours"
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    if (bloc=1 or bloc=3) and statut=4 then statut2="à faire";    /* ou bloc in (1,3) */
    else statut2 = "en cours";


    Si vous ne voulez pas écraser une valeur déjà remplie :

    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    data matable;
      set matable;
      length statut_prov statut2 $10.;
      by id;
      if first.id and bloc=3 and statut=2 then statut2="à valider";
      else if (bloc=1 or bloc=3) and statut=4 then statut2 = "à faire";   /* ou bloc in (1,3) */
      else statut2="en cours";
    run;


    Cordialement,

  7. #7
    Futur Membre du Club
    Vous avez raison. C'est clair dans ma tête mais dur à exprimer à l'écrit.

    Pour la condition, c'est bien un "ET" et non un "ou".

    Il y a un petit décalage entre le code proposé et ce que je souhaite obtenir : le fait d'avoir BLOC=3 et STATUT=4 n'implique pas forcément le statut "à faire", c'est le fait d'avoir BLOC=1 et STATUT=4 et BLOC=3 et STATUT= 4. Toutefois, si je modifie simplement le code en mettant "and" à la place de "or", je ne travaille pas pour un individu ID mais pour toutes les lignes confondues...

  8. #8
    Membre éprouvé
    étape data
    Les instructions s'exécutent en parallèle sur chaque ligne. Si vous remplacez or par and, vous ne travaillez pas pour toutes les lignes confondues, vous demandez à ce qu'une ligne remplisse les conditions bloc=1 et bloc=3 simultanément ce qui est impossible.

    Si ce que je crois comprendre est exact, il n'existe pas d'id pour lequel il y a une ligne bloc=1 et statut=4 et une autre bloc=3 et statut= 4 dans votre table test. Il serait bien de modifier l'étape data pour pouvoir tester les différents cas. Pensez aussi à afficher la table résultat attendu.

    Cordialement,

  9. #9
    Futur Membre du Club
    Oui bien sûr, plutôt un IF imbriqué pardon.

    Voici un exemple de 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
    data matable;
    input ID BLOC STATUT;
    cards;
    1 	1 	1
    1 	2 	3
    1 	3 	4
    2 	1 	1
    2      2       2
    2      3       3
    3 	1 	1
    3 	2 	1
    3 	3 	3
    ;
    run;


    Ci-dessous les résultats attendus :


    [TH]ID[/TH]
    [TH]BLOC[/TH]
    [TH]STATUT[/TH]
    [TH]STATUT2[/TH]
    1 1 1 EN COURS
    1 2 1 EN COURS
    1 3 4 EN COURS
    2 1 4 A FAIRE
    2 2 2 A FAIRE
    2 3 4 A FAIRE
    3 1 1 A VALIDER
    3 2 1 A VALIDER
    3 3 2 A VALIDER

  10. #10
    Membre éprouvé
    manipulation de données
    Un if imbriqué ne change rien... vous travaillez toujours au niveau de l'observation...

    Je ne vois toujours pas d'id avec bloc=1 et statut=4 et bloc=3 et statut=4 dans votre table de départ... et pas non plus d'id avec bloc=3 et statut=2...

    En modifiant votre table de départ :

    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
    data matable;
      input id bloc statut;
      cards;
    1 1 4
    1 2 3
    1 3 4
    2 1 1
    2 2 2
    2 3 3
    3 1 1
    3 2 1
    3 3 2
    ;
    run;
     
    data matable;
      set matable;
      if bloc in (1,3) and statut=4 then temp=1;
      else if bloc=3 and statut=2 then temp=3;
      else temp=0;
    run;
     
    proc univariate data=matable noprint;
      by id;
      var temp;
      output out=temp sum=temp2;
    run;
     
    data matable;
      merge matable temp;
      by id;
      if temp2=3 then statut2="à valider";
      else if temp2=2 then statut2="en cours";
      else statut2="à faire";
    run;


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    id    bloc    statut    temp    temp2     statut2
     1      1        4        1       2      en cours
     1      2        3        0       2      en cours
     1      3        4        1       2      en cours
     2      1        1        0       0      à faire
     2      2        2        0       0      à faire
     2      3        3        0       0      à faire
     3      1        1        0       3      à valider
     3      2        1        0       3      à valider
     3      3        2        3       3      à valider


    Cordialement,

  11. #11
    Futur Membre du Club
    Désolée, ça ne fonctionne toujours pas comme attendu (les 3 premières lignes devraient être "à faire") et je n'ai pas réussi à l'adapter. Tant pis, et merci beaucoup pour le temps accordé à mon problème!

    Cordialement,
    Garpe

  12. #12
    Membre éprouvé
    manipulation de données
    Oui pardon, je suis partie de votre tableau de résultat et non de la définition des statuts :

    si (bloc = 3 et statut = 2) alors statut2 = "à valider",
    sinon si (bloc = 3 et statut = 4) et si (bloc = 1 et statut = 4) alors statut2 = "à faire",
    sinon statut2 = "en cours"
    Il faut inverser les statuts "à faire" et "en cours" dans mon précédent programme :

    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
    data matable;
     input id bloc statut;
     cards;
    1 1 4
    1 2 3
    1 3 4
    2 1 1
    2 2 2
    2 3 3
    3 1 1
    3 2 1
    3 3 2
    ;
    run;
     
    data matable;
      set matable;
      if bloc in (1,3) and statut=4 then temp=1;
      else if bloc=3 and statut=2 then temp=3;
      else temp=0;
    run;
     
    proc univariate data=matable noprint;
      by id;
      var temp;
      output out=temp sum=temp2;
    run;


    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    id    bloc    statut    temp    temp2     statut2
     1      1        4        1       2      à faire
     1      2        3        0       2      à faire
     1      3        4        1       2      à faire
     2      1        1        0       0      en cours
     2      2        2        0       0      en cours
     2      3        3        0       0      en cours
     3      1        1        0       3      à valider
     3      2        1        0       3      à valider
     3      3        2        3       3      à valider


    Cordialement,

###raw>template_hook.ano_emploi###