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 :

Concaténation de plusieurs tables suivie d'un test : résultat bizarre


Sujet :

SAS Base

  1. #1
    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 Concaténation de plusieurs tables suivie d'un test : résultat bizarre
    Bonjour,

    voici un bout de code "simple" au résultat inattendu...

    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
     
    data a;
    id='1';var='rue du general de gaulle';output;
    id='2';var='allee des fleurs';output;
    run;
    data a;set a; maj=upcase(var);run;
     
    data b;
    id='3';var='chemin du four';output;
    id='4';var='hotel des postes';output;
    id='5';var='chateau de moulinsard';output;
    run;
     
    data c; set a b;
    if maj='' then maj=upcase(var);
    run;
     
    proc print data=c;run;

    resultat... (!!!!)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
                      Obs    id    var                         maj
     
                       1     1     rue du general de gaulle    RUE DU GENERAL DE GAULLE
                       2     2     allee des fleurs            ALLEE DES FLEURS
                       3     3     chemin du four              CHEMIN DU FOUR
                       4     4     hotel des post              CHEMIN DU FOUR
                       5     5     chateau de mou              CHEMIN DU FOUR
    Soit SAS ne fonctionne pas comme attendu, soit il y a une subtilité de programmation qui m'échappe...

  2. #2
    Membre chevronné
    Homme Profil pro
    Biostatisticien
    Inscrit en
    Juin 2009
    Messages
    1 206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Irlande

    Informations professionnelles :
    Activité : Biostatisticien
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 206
    Points : 1 868
    Points
    1 868
    Par défaut
    il te manque le by id (d'ailleurs, pense a trier tes donnees. Au cas ou...):


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    DATA c; SET a b;
    by ID;
    IF maj='' then maj=upcase(var);
    run;

  3. #3
    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
    ok merci ça fonctionne effectivement dans le cas où l'on a un identifiant,
    mais dans le cas où l'on n'aurait pas d'identifiant ?

  4. #4
    Membre chevronné
    Homme Profil pro
    Biostatisticien
    Inscrit en
    Juin 2009
    Messages
    1 206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Irlande

    Informations professionnelles :
    Activité : Biostatisticien
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 206
    Points : 1 868
    Points
    1 868
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    proc sort data=a; by var;
    proc sort data=b; by var;
    run;
    DATA c; SET a b;
    by var;
    IF maj='' then maj=upcase(var);
    run;
    Ou si tu veux conserver l'ordre de tes dataset et des observations en entree, tu peux creer une variable de comptage en utilisant _N_ par exemple. Pour ton dataset B (deuxieme entree), recupere le nombre d'obs dans ton dataset A(avec un call symput par exemple), et additionne le au numero lu du dataset B.

    Apres c'est pas ce qu'il y a de plus esthetique. Mais ca doit marcher. Il y a surement mieux.

  5. #5
    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
    mais pourquoi la présence du by influe sur le résultat du if, c'est ce que je ne comprend pas

    Le recopiage de la valeur de la première observation lue à toutes les suivante c'est ça que je ne comprend pas.

  6. #6
    Membre chevronné
    Homme Profil pro
    Biostatisticien
    Inscrit en
    Juin 2009
    Messages
    1 206
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Irlande

    Informations professionnelles :
    Activité : Biostatisticien
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 206
    Points : 1 868
    Points
    1 868
    Par défaut
    Si tu ne mets pas de by, tu vas juster "coller" un dataset sous l'autre, tels qu'ils sont. Si tu mets un by, tu specifie une cle d'ordonnacement:

    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 a;
    id='1';var='rue du general de gaulle';output;
    id='2';var='allee des fleurs';output;
    run;
    DATA a;SET a; maj=upcase(var);run;
     
    DATA b;
    id='0';var='chemin du four';output;
    id='4';var='hotel des postes';output;
    id='5';var='chateau de moulinsard';output;
    run;
     
    DATA c; SET a b;
    by ID;
    IF maj='' then maj=upcase(var);
    run;
    Chemin du four apparait en premier dans ce cas. Pour en revenir a ton exemple initial, pourquoi il y a une coquille au niveau de la variable maj, la, y a une subtilite qui m'echappe. mais je ne doute pas que quelqu'un pourra t'eclairer sur ce que sas fait en arriere plan durant la phase d'execution...

  7. #7
    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 : 47
    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 !
    Comme ce n'est pas un MERGE mais un SET, je pense que SAS ne lit dans son vecteur de travail que les variables déjà existantes. C'est comme si MAJ faisait l'objet d'un RETAIN : à la 1e observation lue dans la table B, SAS remplit la variable MAJ puisqu'elle est vide (la condition est vraie). Mais à la 2e observation de B, MAJ est déjà remplie (par la valeur précédente) et il n'y a aucun changement.
    Le BY ajoute une sorte de réinitialisation du vecteur de travail à chaque fois qu'on change de bloc, puisqu'il y a des appariements par blocs.

    Le plus simple serait soit de faire un UPCASE systématiquement, soit de tester la provenance des observations avec des IN comme dans un MERGE.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    DATA c; SET a b (IN=dans_b) ;
    IF dans_b then maj=upcase(var);
    run;
    Bon courage.
    Olivier

    PS : une mise à jour pour ajouter un exemple qui accrédite cette hypothèse de RETAIN implicite sur les variables non communes aux deux tables. Pour le moment, je n'ai pas trouvé dans la doc SAS de passage qui irait dans ce sens (mais rien non plus qui le contredirait).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    DATA work.class ;
      SET sashelp.class ;
      a = 1 ;
    RUN ;
    DATA work.class2 ;
      SET work.class sashelp.class ;
      a = SUM(a, 1) ;
    RUN ;
    Si quelqu'un trouve une référence claire sur la question, et sur le pourquoi du non-nettoyage d'une partie du PDV avant de charger une nouvelle observation, ça fera la lumière sur cette affaire.

  8. #8
    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 : 47
    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
    Bon, je crois que j'ai trouvé le bout de doc qui explique pourquoi les variables issues de la 1e table ne sont pas automatiquement "vidées" dans le vecteur de travail avant de lire une nouvelle observation : c'est au point 2
    SAS sets the newly created program variables to missing in the program data vector (PDV).
    Newly created seulement. Pour les variables existantes, il "suffit" d'aller les lire dans la table SAS citée dans le SET. Sauf que dans ton exemple, Jérôme, MAJ n'est pas créée au cours de l'étape DATA. Donc en arrivant à la 1e observation de la seconde table, SAS cherche une valeur de MAJ pour mettre dans le PDV. Il n'en trouve pas, le IF est vrai. Il alimente MAJ. Puis en arrivant à la 2e observation de la seconde table, SAS a compris le truc : inutile de chercher une valeur de MAJ dans la table SAS, il n'y en aura pas. Mais comme ce n'est pas une variable nouvelle, c'est comme si elle faisait l'objet d'un RETAIN : pas d'effacement de la valeur précédente.
    D'où nos résultats, sur ton exemple et le mien.

    Bon week-end.
    Olivier

  9. #9
    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
    ok merci Olivier d'avoir levé une partie de l'ombre sur ce résultat surprenant.

    Il faut dire que le code a sans doute été écrit avec un peu d'empressement de ma part et le souhait de minimiser les étapes, ce qui ont le voit peut être glissant.

    Rétrospectivement, je me dis que c'est sans doute pas la première fois que j'ai écrit une chose similaire, mais c'est la première que je m'en aperçois...

    J'ai peur rétrospectivement pour ce que j'ai déjà écris dans le passé...

  10. #10
    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 : 47
    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
    Toujours à la recherche d'une doc claire sur la question, j'ai mis la main sur un document de Ian Whitlock sur l'étape Data : page 13 (en bas) on peut lire
    SAS does not reset values of variables coming from a SAS data set to missing at the beginning of each iteration of the ILDS.
    (ILDS=Implied Loop of the Data Step : la boucle implicite du SET/MERGE/INFILE)
    Donc on n'a besoin d'un RETAIN que pour les variables nouvelles (créées). Les autres ne sont pas automatiquement éliminées du vecteur de travail avant de charger une nouvelle observation, et comme on lit même (page 14, 1e ligne)
    Separate buffers are set up to read each [data] set.
    Il y a physiquement plusieurs zones mémoires : une par observation à lire dans une table SAS. Donc en attaquant la 2e table, comme on passe par une autre zone mémoire que lors de la lecture de la 1e, on n'écrase rien des variables spécifiques à la 1e table.
    Bref, cette rémanence est logique et prévisible... et devrait nous inciter à beaucoup de prudence en empilant des tables à l'avenir !

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/09/2013, 10h07
  2. [D7][BDE]Concaténation de plusieurs tables
    Par fthdz dans le forum Bases de données
    Réponses: 4
    Dernier message: 02/04/2007, 22h36
  3. A propos d'une requête SQL sur plusieurs tables...
    Par ylebihan dans le forum Langage SQL
    Réponses: 2
    Dernier message: 14/09/2003, 16h26
  4. Une seule table VS plusieurs tables
    Par LostControl dans le forum Requêtes
    Réponses: 1
    Dernier message: 11/08/2003, 10h56
  5. [SQL] Sélection ds plusieurs table
    Par lord_paco dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 24/07/2003, 17h53

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