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 :

Regrouper des clients au sein d'une "même famille"


Sujet :

SAS Base

  1. #1
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut Regrouper des clients au sein d'une "même famille"
    Bonjour à tous,

    Je suis confrontée à une problematique et je ne sais pas par quel bout commencer.

    Le contexte, j'ai des clients qui sont sont au sein d'une même famille grâce à un compteur qui permet de récupérer les membres, jusqu'ici tout va bien. Il s'avère que parfois une même personne se retouve dans plusieurs familles et mon objectif est de regrouper ces dernières au sein de la même avec un compteur unique.

    Exemple théroqrique :

    La famille (A B C) est regroupée sous le compteur 1
    La famille (D A B) est regroupée sous le compteur 2

    Il me manque l'association C et D au sein d'une même famille donc mon but est de dire que (A B C D) forme une seule et même famille avec le compteur 1 ou 2.

    Exemple qui se reflète dans les données de tests :

    Client compteur1 compteur2 compteur3
    13135819 3724 4126 77070
    14115819 3724 4126 76468
    258111377 4126 76468 77070
    260312693 3724 76468 77070
    J'ai toujours un compteur qui represente 3 personnes, mais j'ai aucun compteur qui me permet de dire que les 4 personnes sont ensemble.
    Voic le jeu de données pour test.
    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
     
     
    DATA population;
    INPUT 
    compteur
    client
    freq;
    DATALINES;
    1774 7325135 4
    1774 332343475 4
    1774 515384640 4
    1774 57321319 4
    3724 260312693 3
    3724 14115819 3
    3724 13135819 3
    4126 258111377 3
    4126 14115819 3
    4126 13135819 3
    16815 839316259 3
    16815 57321319 3
    16815 7325135 3
    76468 258111377 3
    76468 14115819 3
    76468 260312693 3
    77070 260312693 3
    77070 258111377 3
    77070 13135819 3
    99404 332343475 2
    99404 7325135 2
    154377 515384640 2
    154377 7325135 2
    248196 839316259 2
    248196 57321319 2
    1 14814 4
    1 124150319 4
    1 178040920 4
    1 753052522 4
    2 27835 2
    2 981328900 2
    3 33215 2
    3 108048911 2
    4 59315 2
    4 96092617 2
    5 85031 2
    5 799322987 2
    6 215817 3
    6 115730429 3
    6 315326243 3
    7 300054 2
    7 901389050 2
    8 300405 2
    8 6341406 2
    9 300851 2
    9 189378210 2
     
    ;
    RUN;
    Je suis preneuse d'idée et/ou de pistes de solutions.
    La troisième variable représente la frequence de chaque compteur elle me permet par la suite de trier les clients avec le compteur le plus fréquents et de faire un FIRTS.CLIENT, cela marche pour 95% des cas sauf la situation décrite ci-dessus car je me retrouve avec un client TOUT SEUL.

    Petite question : comment fait-on pour afficher en "QUOTE" ou "code" les variables correctement (ie correctement alignées)?

    Merci de votre aide.

  2. #2
    Rédacteur

    Homme Profil pro
    SAS ALLIANCE SILVER. Consultant et formateur SAS et Cognos.
    Inscrit en
    Avril 2009
    Messages
    2 497
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : SAS ALLIANCE SILVER. Consultant et formateur SAS et Cognos.
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2009
    Messages : 2 497
    Points : 6 064
    Points
    6 064
    Par défaut
    Ca s'appelle le Bill of Materials. Il y a même une proc BOM pour gérer ces cas.

    Autrement, tu peux le faire manuellement.

    voici une suggestion avec ton exemple que j'ai doublé pour avoir deux familles. Il te faut l'adapter pour prendre en compte compteur3.

    Par contre, je suis désolé, je n'ai pas compris les données de test et encore moins le poids. aussi j'ai pris ton premier exemple.

    Je te souhaite bon courage.

    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
    data test;
    input Client	 compteur1	compteur2	compteur3;
    datalines;
    13135819	3724	4126	77070
    14115819	3724	4126	76468
    258111377	4126	76468	77070
    260312693	3724	76468	77070
    23135819	4724	5126	77070
    24115819	4724	5126	76468
    358111377	5126	76468	77070
    360312693	3724	76468	77070
    ;
    run;
     
    data test2;
    retain ID 0 famille1 famille2;
    set test;
    if famille1 ne compteur1 and famille2 ne compteur1 and famille1 ne compteur2 and famille2 ne compteur2 then do;
              ID+1;
              famille1=compteur1;
              famille2=compteur2;
            end;
            else if famille1 ne compteur1 and famille2 ne compteur1 then do;
              if famille1=compteur2 then do;
                famille2=compteur1;
              end;
              else do;
                famille1=compteur1;
              end;
        end;
            else if famille1 ne compteur2 and famille2 ne compteur2 then do;
              if famille1=compteur1 then do;
                famille2=compteur2;
              end;
              else do;
                famille1=compteur2;
              end;
        end;
     
        if famille1 ne compteur1 and famille2 ne compteur1 then do;
              ID+1;
              famille1=compteur1;
              famille2=.;
            end;
         if famille1 ne compteur2 and famille2 ne compteur2 then do;
              ID+1;
              famille1=compteur2;
              famille2=.;
            end;
      ;
      run;
    N'oubliez pas de cliquer sur lorsque votre problème est réglé !

  3. #3
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut Merci
    Bonjour,

    Merci de ta réponse.
    J'avais tenté dans un premier temps de mettre mes données sous la forme de tes données de test grâce au Array:
    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
     
    DATA population;
    INPUT 
    compteur
    client
    freq;
    DATALINES;
    1774 7325135 4
    1774 332343475 4
    1774 515384640 4
    1774 57321319 4
    3724 260312693 3
    3724 14115819 3
    3724 13135819 3
    4126 258111377 3
    4126 14115819 3
    4126 13135819 3
    16815 839316259 3
    16815 57321319 3
    16815 7325135 3
    76468 258111377 3
    76468 14115819 3
    76468 260312693 3
    77070 260312693 3
    77070 258111377 3
    77070 13135819 3
    99404 332343475 2
    99404 7325135 2
    154377 515384640 2
    154377 7325135 2
    248196 839316259 2
    248196 57321319 2
    1 14814 4
    1 124150319 4
    1 178040920 4
    1 753052522 4
    2 27835 2
    2 981328900 2
    3 33215 2
    3 108048911 2
    4 59315 2
    4 96092617 2
    5 85031 2
    5 799322987 2
    6 215817 3
    6 115730429 3
    6 315326243 3
    7 300054 2
    7 901389050 2
    8 300405 2
    8 6341406 2
    9 300851 2
    9 189378210 2
     
    ;
    RUN;
     
     proc sort data=population out=pop_trie;
     by client;
     run;
     
     
    DATA pop;
    SET pop_trie ; 
    BY client;
    IF FIRST.client then id=0;
    id+1;
    nomvar=COMPRESS("Compteur"!!id);
    valeur=compteur;
    output;
     
    RUN;
     
    proc transpose DATA=pop out=pop_tr (DROP= _name_);
    BY  client ;
    var valeur ;
    id nomvar;
    run;
     
    DATA Pop_final;
    SET pop_tr;
    Array compt(*)   compteur:;
    run;
    Dans mes données de test je me retouve avec 4 compteurs...(et ca risque d'être plus sur l'intégralité de mes données à moins sous que je sous traite les cas à problèmes et les réintègre ensuite, même là je ne peux garantir que le nombre sera fixe dans le temps).

    Le défi revient à généraliser le programme que tu proposes. En le testant rapidement il ne fonctionne pas tout à fait correctement (il met mes cas "normaux" au sein de la même famille).

    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
     
    DATA test2;
    	retain ID 0 famille1 famille2;
    	SET Pop_final;
     
    	IF famille1 ne compteur1 AND famille2 ne compteur1 AND famille1 ne compteur2 AND famille2 ne compteur2 then
    		do;
    			ID+1;
    			famille1=compteur1;
    			famille2=compteur2;
    		end;
    	else IF famille1 ne compteur1 AND famille2 ne compteur1 then
    		do;
    			IF famille1=compteur2 then
    				do;
    					famille2=compteur1;
    				end;
    			else
    				do;
    					famille1=compteur1;
    				end;
    		end;
    	else IF famille1 ne compteur2 AND famille2 ne compteur2 then
    		do;
    			IF famille1=compteur1 then
    				do;
    					famille2=compteur2;
    				end;
    			else
    				do;
    					famille1=compteur2;
    				end;
    		end;
     
    	IF famille1 ne compteur1 AND famille2 ne compteur1 then
    		do;
    			ID+1;
    			famille1=compteur1;
    			famille2=.;
    		end;
     
    	IF famille1 ne compteur2 AND famille2 ne compteur2 then
    		do;
    			ID+1;
    			famille1=compteur2;
    			famille2=.;
    		end;
    	;
    run;
    Je vais continuer d'explorer la piste, et regarder comment fonctionne la PROC BOM.

    Sinon j'avais comme solution de partir de mes données "à problème" et remonter à la source pour aller chercher les clients avec lequel ils sont liés (car j'ai cette info de base) et lui associer le compteur que ces derniers portent. Ils seront ainsi réuni dans la même famille.
    Cette solution n'est pas parfaite car il se peut que je me retrouve encore dans la situation décrite dans ma problématique. Mais l'avantage c'est que je réduirai pas mal les personnes concernées.
    Merci beaucoup.

  4. #4
    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,
    Tu peux regarder également côté proc cluster et proc tree qui te permettent de travailler directement sur ta data initiale (population). C’est la table Pop_Clust que te cherche me semble-il ?

    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
    ODS output ClusterHistory=Pop_history;            
    proc cluster data=population  
        method=ward 
        simple pseudo rsquare ccc
        outtree=Pop_tree standard
        print=8 ;     
    
        var compteur client ;            
        copy freq ;            
        Run;
    ODS output close;    
    
    proc tree data=Pop_tree 
        horizontal 
        out=Pop_Clust Nclusters=3  ;            
        copy compteur client freq;            
    
    run;
    J’espère que cette piste te servira.
    Cdt Ward

  5. #5
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Avec la proc Cluster je pense que je m'éloigne de mon problème, je ne cherche pas à mettre créer des classes selon des critères statistiques, je cherche à mettre en groupe des personnes qui aurait du l'être car ils ont au moins une personne en commun...genre l'ami de mon ami est mon ami.

    Si je reviens sur mes données d'origines voici ce que j'ai :

    Le compteur 1774 relie ces 4 clients:

    1774 7325135
    1774 57321319
    1774 515384640
    1774 332343475

    Le compteur 16815 relie ces 3 clients

    16815 839316259
    16815 57321319
    16815 7325135

    Le 99404 relie ces 2 clients

    99404 332343475
    99404 7325135

    Le 154377 relie ces 2 clients

    154377 7325135
    154377 515384640

    Le 248196 relie ces 2 clients

    248196 57321319
    248196 839316259

    La colonne FREQ recense les chiffres 4,3,2,2,2...nombre de fois du compteur.

    Dans mon traitement je trie les clients et les fréquences de manière descendante pour donner la priorité au compteur le plus fréquent, en éliminant les doublons (ligne barrée) :

    ca donne

    1774 7325135 4
    16815 7325135 3
    99404 7325135 2

    1774 57321319 4
    16815 57321319 3
    248196 57321319 2

    1774 332343475 4
    99404 332343475 2
    1774 515384640 4
    154377 515384640 2
    16815 839316259 3
    248196 839316259 2

    À la fin mon client en gras se retrouve tout seul...alors qu'il fait bel et bien partie du lot...juste parcequ'il n'existe pas la relation double avec le 7325135 qui lui aurait permis d'être dans le lot 1774.


    C'est pour cela que je tente de recréer la relation avec le 7325135 en passant par les autres personnes avec qui le lien peut-être fait notamment à travers le compteur 16815.

    Si je mets en face de chaque client tous les compteurs auquel il participe j'ai une table du genre (client copmt1 compt 2 compt 3 compt 4)

    7325135 1774 16815 99404 154377
    57321319 1774 16815 248196 .
    332343475 1774 99404 . .
    515384640 1774 154377 . .
    839316259 16815 248196 . .


    Le best serait de pouvoir dire du moment que je reprère parmi tous les compteurs un qui est égal à celui qu'un client possède alors il s'agit des personnes d'un même groupe.

    Merci.

  6. #6
    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 Mariam,

    quelle est la volumétrie approximative de ta base ?

  7. #7
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    300 000 clients parmi lesquels environ 290 ne sont pas matchés correctement.


    J'avais avancé avec la solution de récupérer le client associé (de mon client qui était tout seul) et lui assigné le compteur de ce dernier...j'ai plus de client isolé mais je me constate que mon appariement n'est pas à 100% fiable.

    Merci.

  8. #8
    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, je teste un truc, par contre pour être sûr de bien comprendre parce que j'ai un peu de mal à comprendre ta notion de "compteur".

    Dans tes données, les individus sont associés par groupes de 3,2 ou même 1 dans un "compteur".
    Et tu veux reconstruire des "familles", une famille étant composée par l'ensemble des individus liés entre eux par un succession quelconque de "compteurs" ?

    Un "compteur" est donc un sous ensemble d'individus appartenant à une même famille, et identifié (le sous ensemble) par un identifiant unique le "compteur" c'est ça ?

  9. #9
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    Un "compteur" est donc un sous ensemble d'individus appartenant à une même famille, et identifié (le sous ensemble) par un identifiant unique le "compteur" c'est ça ?
    C'est tout à fait cela. Le compteur est la variable unique (l'identifiant) qui me permets de dire que les "clients" qui portent le même compteur font partie de la même famille (en fait ce sont plus des doubles pour rejoindre un de mes anciens post).
    Donc au minimum il y a deux clients par compteur. Un compteur tout seul est problématique (cela veut dire que mon traitement a une carence quelque part), le maximum observé pour le moment est de 42 clients pour un même compteur.

    Je prépare un fichier excel pour mieux illustrer mon traitement.

  10. #10
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut Fichier illustrateur
    Un petit fichier excel pour démontrer d'où je pars et ce que je souhaite...

    Merci pour vos différentes pistes ...enrichissantes !
    Fichiers attachés Fichiers attachés

  11. #11
    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
    Pas trop de solutions satisfaisantes.

    Voici une solution en prenant en entrée une table comportant uniquement deux variables : IdClient et son Compteur associé.
    Une ligne par IdClient et Compteur. Si plusieurs compteurs sur un même IdClient alors autant de lignes que de compteur.

    Je te demandais la taille de tes données, car cette solution nécessite de charger les données en mémoire vive (objets Hash).
    Avec 300 000 IdClients ça devrait le faire normalement ( si tu dispose de 2Go par exemple ça devrait être amplement suffisant).

    Ci-joint le 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
    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
    data pseudoFamille;
    infile datalines;
    length IdClient $15. PseudoFamille $8. ;
    Input IdClient $ PseudoFamille $;
    datalines;
    Charles A
    Marie A
    Julie A
    Celestine B
    Xavier B
    Karl B
    Xavier C
    Pierre-Henri C
    Sophie C
    Pierre D
    Marie D
    Celestine D
    Amédée E
    Laurence E
    Clémence E
    ;
    run;
     
     
     
    data _null_;
    set pseudoFamille end=eof;
    length VFamille $8. ;
    if _n_=1 then 	do;
     
    DECLARE HASH Client (DATASET:"PseudoFamille",multidata:"YES");
    Client.DefineKey("IdClient" );
    Client.DefineData("IdCLient",'PseudoFamille');
    Client.DefineDone();
     
     
    DECLARE HASH PSF (DATASET:"PseudoFamille",multidata:"YES");
    PSF.DefineKey("PseudoFamille" );
    PSF.DefineData("PseudoFamille","IdClient");
    PSF.DefineDone();
     
     
    DECLARE HASH LISTE (multidata:"NO");
    LISTE = _NEW_ HASH();
    LISTE.DefineKey('PseudoFamille');
    LISTE.DefineDone();
    DECLARE HITER HLISTE("LISTE");
     
     
    DECLARE HASH NFAM (multidata:"NO");
    NFAM = _NEW_ HASH();
    NFAM.DefineKey('IdClient');
    NFAM.DefineData('IdCLient','VFamille');
    NFAM.DefineDone();
    DECLARE HITER HNFAM("NFAM");
     
     
    DECLARE HASH FAMILLE (multidata:"NO");
    FAMILLE = _NEW_ HASH();
    FAMILLE.DefineKey('IdClient');
    FAMILLE.DefineData("IdClient","VFamille");
    FAMILLE.DefineDone();
     
     
     
    				end;
     
    RC_FAMILLE=FAMILLE.FIND();
    IF RC_FAMILLE^=0	THEN	DO; /***si RC_Famille^=0 on a trouvé un chef de famille ***/
    	RC_NFam=NFam.Clear();
    	RC_Liste=Liste.Clear();
    	VFamille=PseudoFamille; /** l'identifiant de famille est le premier identifiant de pseudofamille du chef de famille **/
    	RC_NFAM=NFAM.ADD(); /** le chef de famille est le premier individu de sa famille **/
    	Test=1;
     
    		DO UNTIL (Test=0);
     
    		Test1=0;Test2=0;
    			RC_HNFAM=HNFAM.First();
    				DO UNTIL (RC_HNFAM^=0);
    					RC_Client=Client.Find();
    						DO UNTIL (RC_Client^=0);
    							RC_Liste=Liste.Find();
    							IF RC_Liste^=0 THEN DO;RC_Liste=Liste.ADD(); Test1=1;END;
    							RC_Client=Client.Find_Next();
    						END;
    				RC_HNFAM=HNFAM.Next();
    				END;
     
    			RC_HListe=HListe.First();
    				DO UNTIL (RC_HListe^=0);
    					RC_PSF=PSF.Find();
    						DO UNTIL (RC_PSF^=0);
    							RC_NFAM=NFAM.Find();
    							IF RC_NFAM^=0 THEN DO;RC_NFAM=NFAM.ADD();Test2=1;END;
    							RC_PSF=PSF.Find_Next();
    						END;
    				RC_HListe=HListe.Next();
    				END;
     
    test=MAX(test1,test2);
     
     
    		END;
     
     
    RC_HNFAM=HNFAM.First();
    DO UNTIL (RC_HNFAM^=0);
    RC_FAMILLE=FAMILLE.ADD();
    RC_HNFAM=HNFAM.Next();
    END;
     
    						END;
     
    if eof then RC=FAMILLE.OUTPUT(dataset:'FAMILLE');
     
     
    run;
     
     
    proc print data=famille;run;
    et le résultat

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
                                                   Obs    IdClient        VFamille
     
                                                     1    Celestine          A
                                                     2    Karl               A
                                                     3    Laurence           E
                                                     4    Julie              A
                                                     5    Pierre-Henri       A
                                                     6    Xavier             A
                                                     7    Clémence           E
                                                     8    Sophie             A
                                                     9    Amédée             E
                                                    10    Charles            A
                                                    11    Marie              A
                                                    12    Pierre             A
    en espérant que ça réponde à ta demande, et qu'il n'y ai pas de bugs...


    Edit : le paramètre par défaut hashexp: des objets HASH est de 8 , cependant avec plusieurs centaines de milliers d'éléments il faudra sans doute l'augmenter pour obtenir de meilleures performances, d'expérience si N est le nombre d'élément il doit être fixé à FLOOR(LOG(N)/LOG(2))-4 soit environ 14 dans ton cas (pour "Client" et "PSF" principalement).

  12. #12
    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
    En reprenant tes données du document Illustration.xlsx

    le code fait bien le job attendu

    1 - Création de la table PseudoFamille à partir de tes 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
    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
     
    data mdsas;
    infile datalines;
    length IdClient1 $15. IdClient2 $15. ;
    Input IdClient1 $ IdClient2 $;
    datalines;
    208066019	354077326
    208066019	905321599
    354077326	24388894
    354077326	208066019
    750639762	24388894
    750639762	905321599
    7325135	57321319
    7325135	332343475
    7325135	515384640
    13135819	14115819
    13135819	260312693
    14115819	13135819
    14115819	258111377
    57321319	7325135
    57321319	839316259
    258111377	14115819
    258111377	260312693
    260312693	13135819
    260312693	258111377
    332343475	7325135
    515384640	7325135
    839316259	57321319
    ;
    run;
     
    data mdsas; set mdsas;
    length PseudoFamille $3. ;
    PseudoFamille=_n_;
    run;
     
    data PseudoFamille;
    set mdSAS;
    Length IdClient $15. ;
    IdClient=IdClient1;OUTPUT;
    IdClient=IdClient2;OUTPUT;
    KEEP IdCLient PseudoFamille;
    run;
    2- Exécution du code précédent

    3- Résultat après proc sort sur VFamille

    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
                                                    Obs    IdClient     VFamille
     
                                                      1    24388894         1
                                                      2    750639762        1
                                                      3    905321599        1
                                                      4    354077326        1
                                                      5    208066019        1
                                                      6    332343475        7
                                                      7    7325135          7
                                                      8    839316259        7
                                                      9    515384640        7
                                                     10    57321319         7
                                                     11    14115819        10
                                                     12    13135819        10
                                                     13    260312693       10
                                                     14    258111377       10

    Te reste à être parcimonieuse sur les longueurs de variable (IdClient et PseudoFamille/Compteur) de sorte que tout ce petit monde tienne dans les objets HASH sans faire de dépassement mémoire (trois "copies" de ta base seront chargées en mémoire vive, via les objets "Client","PSF" et dans une moindre mesure "Famille").

  13. #13
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    Excuse-moi j'avais pas vu le message précédent...il est juste 8h du matin ici

    Le code ne bug pas, cependant j'ai pas le même résultat que toi (bizarre tout de même) !

    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
     
     
     
    Obs.	IdClient	VFamille
    1	20806601935407	1
    2	20806601990532	1
    3	35407732620806	2
    4	35407732624388	2
    5	75063976290532	3
    6	75063976224388	3
    7	73251353323434	4
    8	73251355732131	4
    9	13135819141158	5
    10	73251355153846	5
    11	13135819260312	6
    12	14115819131358	6
    13	57321319732513	7
    14	14115819258111	7
    15	25811137714115	8
    16	57321319839316	8
    17	25811137726031	9
    18	26031269313135	9
    19	26031269325811	10
    20	33234347573251	10
    21	83931625957321	11
    22	51538464073251	11
    Tout les numéros de clients sont concatenés dans IdClient.

  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
    Tu as quelle version de SAS ?

    Edit : modifie cette partie du code chez toi, pour qu'il lise convenablement la table, de ton côté la table a été mal lue (je ne sais pas pourquoi...), forcément si les données initiales ne sont pas les mêmes, les résultats sont différents

    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
     
     
    DATA mdsas;
    INFILE datalines;
    length IdClient1 $15. IdClient2 $15. ;
    Input IdClient1 $ IdClient2 $;
    datalines;
    208066019	354077326
    208066019	905321599
    354077326	24388894
    354077326	208066019
    750639762	24388894
    750639762	905321599
    7325135	57321319
    7325135	332343475
    7325135	515384640
    13135819	14115819
    13135819	260312693
    14115819	13135819
    14115819	258111377
    57321319	7325135
    57321319	839316259
    258111377	14115819
    258111377	260312693
    260312693	13135819
    260312693	258111377
    332343475	7325135
    515384640	7325135
    839316259	57321319
    ;
    run;
    Je t'ai demandé quelle version tu as parce que le code marche en 9.2 (et ultérieurs ?) mais pas en 9.1.

    Le récapitulatif du code chez moi est

    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
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
     
    DATA mdsas;
    INFILE datalines;
    length IdClient1 $15. IdClient2 $15. ;
    Input IdClient1 $ IdClient2 $;
    datalines;
    208066019	354077326
    208066019	905321599
    354077326	24388894
    354077326	208066019
    750639762	24388894
    750639762	905321599
    7325135	57321319
    7325135	332343475
    7325135	515384640
    13135819	14115819
    13135819	260312693
    14115819	13135819
    14115819	258111377
    57321319	7325135
    57321319	839316259
    258111377	14115819
    258111377	260312693
    260312693	13135819
    260312693	258111377
    332343475	7325135
    515384640	7325135
    839316259	57321319
    ;
    run;
     
    DATA mdsas; SET mdsas;
    length PseudoFamille $3. ;
    PseudoFamille=_n_;
    run;
     
    DATA PseudoFamille;
    SET mdSAS;
    Length IdClient $15. ;
    IdClient=IdClient1;OUTPUT;
    IdClient=IdClient2;OUTPUT;
    KEEP IdCLient PseudoFamille;
    run;
     
     
     
    DATA _null_;
    SET pseudoFamille end=eof;
    length VFamille $8. ;
    IF _n_=1 then 	do;
     
    DECLARE HASH Client (DATASET:"PseudoFamille",multidata:"YES");
    Client.DefineKey("IdClient" );
    Client.DefineData("IdCLient",'PseudoFamille');
    Client.DefineDone();
     
     
    DECLARE HASH PSF (DATASET:"PseudoFamille",multidata:"YES");
    PSF.DefineKey("PseudoFamille" );
    PSF.DefineData("PseudoFamille","IdClient");
    PSF.DefineDone();
     
     
    DECLARE HASH LISTE (multidata:"NO");
    LISTE = _NEW_ HASH();
    LISTE.DefineKey('PseudoFamille');
    LISTE.DefineDone();
    DECLARE HITER HLISTE("LISTE");
     
     
    DECLARE HASH NFAM (multidata:"NO");
    NFAM = _NEW_ HASH();
    NFAM.DefineKey('IdClient');
    NFAM.DefineData('IdCLient','VFamille');
    NFAM.DefineDone();
    DECLARE HITER HNFAM("NFAM");
     
     
    DECLARE HASH FAMILLE (multidata:"NO");
    FAMILLE = _NEW_ HASH();
    FAMILLE.DefineKey('IdClient');
    FAMILLE.DefineData("IdClient","VFamille");
    FAMILLE.DefineDone();
     
     
     
    				end;
     
    RC_FAMILLE=FAMILLE.FIND();
    IF RC_FAMILLE^=0	THEN	DO; /***si RC_Famille^=0 on a trouvé un chef de famille ***/
    	RC_NFam=NFam.Clear();
    	RC_Liste=Liste.Clear();
    	VFamille=PseudoFamille; /** l'identifiant de famille est le premier identifiant de pseudofamille du chef de famille **/
    	RC_NFAM=NFAM.ADD(); /** le chef de famille est le premier individu de sa famille **/
    	Test=1;
     
    		DO UNTIL (Test=0);
     
    		Test1=0;Test2=0;
    			RC_HNFAM=HNFAM.First();
    				DO UNTIL (RC_HNFAM^=0);
    					RC_Client=Client.Find();
    						DO UNTIL (RC_Client^=0);
    							RC_Liste=Liste.Find();
    							IF RC_Liste^=0 THEN DO;RC_Liste=Liste.ADD(); Test1=1;END;
    							RC_Client=Client.Find_Next();
    						END;
    				RC_HNFAM=HNFAM.Next();
    				END;
     
    			RC_HListe=HListe.First();
    				DO UNTIL (RC_HListe^=0);
    					RC_PSF=PSF.Find();
    						DO UNTIL (RC_PSF^=0);
    							RC_NFAM=NFAM.Find();
    							IF RC_NFAM^=0 THEN DO;RC_NFAM=NFAM.ADD();Test2=1;END;
    							RC_PSF=PSF.Find_Next();
    						END;
    				RC_HListe=HListe.Next();
    				END;
     
    test=MAX(test1,test2);
     
     
    		END;
     
     
    RC_HNFAM=HNFAM.First();
    DO UNTIL (RC_HNFAM^=0);
    RC_FAMILLE=FAMILLE.ADD();
    RC_HNFAM=HNFAM.Next();
    END;
     
    						END;
     
    IF eof then RC=FAMILLE.OUTPUT(dataset:'FAMILLE');
     
     
    run;
     
    proc sort data=famille; by VFamille; 
    proc print DATA=famille;run;
    et me donne en résultat

    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
     
    
                                              The SAS System          14:05 Tuesday, June 17, 2014   2
     
                                       Obs    IdClient     VFamille
     
                                         1    24388894         1
                                         2    750639762        1
                                         3    905321599        1
                                         4    354077326        1
                                         5    208066019        1
                                         6    332343475        7
                                         7    7325135          7
                                         8    839316259        7
                                         9    515384640        7
                                        10    57321319         7
                                        11    14115819        10
                                        12    13135819        10
                                        13    260312693       10
                                        14    258111377       10
    comme tu vois je viens de le relancer


    La table mdSAS doit ressembler à ça

    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
     
                                                                  Pseudo
                                 Obs    IdClient1    IdClient2    Famille
     
                                   1    208066019    354077326       1
                                   2    208066019    905321599       2
                                   3    354077326    24388894        3
                                   4    354077326    208066019       4
                                   5    750639762    24388894        5
                                   6    750639762    905321599       6
                                   7    7325135      57321319        7
                                   8    7325135      332343475       8
                                   9    7325135      515384640       9
                                  10    13135819     14115819       10
                                  11    13135819     260312693      11
                                  12    14115819     13135819       12
                                  13    14115819     258111377      13
                                  14    57321319     7325135        14
                                  15    57321319     839316259      15
                                  16    258111377    14115819       16
                                  17    258111377    260312693      17
                                  18    260312693    13135819       18
                                  19    260312693    258111377      19
                                  20    332343475    7325135        20
                                  21    515384640    7325135        21
                                  22    839316259    57321319       22
    et elle génère la table pseudoFamille

    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
     
     
                                              Pseudo
                                       Obs    Famille    IdClient
     
                                         1       1       208066019
                                         2       1       354077326
                                         3       2       208066019
                                         4       2       905321599
                                         5       3       354077326
                                         6       3       24388894
                                         7       4       354077326
                                         8       4       208066019
                                         9       5       750639762
                                        10       5       24388894
                                        11       6       750639762
                                        12       6       905321599
                                        13       7       7325135
                                        14       7       57321319
                                        15       8       7325135
                                        16       8       332343475
                                        17       9       7325135
                                        18       9       515384640
                                        19      10       13135819
                                        20      10       14115819
                                        21      11       13135819
                                        22      11       260312693
                                        23      12       14115819
                                        24      12       13135819
                                        25      13       14115819
                                        26      13       258111377
                                        27      14       57321319
                                        28      14       7325135
                                        29      15       57321319
                                        30      15       839316259
                                        31      16       258111377
                                        32      16       14115819
                                        33      17       258111377
                                        34      17       260312693
                                        35      18       260312693
                                        36      18       13135819
                                        37      19       260312693
                                        38      19       258111377
                                        39      20       332343475
                                        40      20       7325135
                                        41      21       515384640
                                        42      21       7325135
                                        43      22       839316259
                                        44      22       57321319
    ensuite c'est le code à proprement dit (dans la DATA _NULL_ )

  15. #15
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    J'ai trouvé il était où mon problème...mais j'ai honte de dire où :mouarf:

    C'est géniale, vais tester cela sur l'ensemble de ma table...c'est la première fois de ma vie que je fais rouler un code en HASH !!!!:aie::yaisse3::yaisse3:

    Je vous redonnes des nouvelles ;)

    Je suis en EG 5.1...SAS 9.3 je crois !

  16. #16
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut
    Bonjour,

    Je viens de faire rouler le code sur l'ensemble de mes données (ça roule vite), il n'y a pas de bug mais dans la table famille VFamille prend toujours la valeur 1
    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
     
     
    378151	1
    1343550	1
    1344352	1
    6321759	1
    6364945	1
    6471017	1
    7368316	1
    7383552	1
    8301488	1
    8336001	1
    9373987	1
    11321916	1
    12196510	1
    13114519	1
    13170117	1
    13397283	1
    14313688	1
    15192230	1
    15367535	1
    Premier 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
     
     
    15         DATA TABLE_POUR_HASH;
    16         SET FUS_CLIPOT_DREAP;
    17         length PseudoFamille $3. ;
    18         PseudoFamille=_n_;
    19         Rename no_seq_cli=IdClient1;
    20         Rename no_seq_cli1=IdClient2;
    21         run;
     
    NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
          18:15   
    NOTE: There were 317124 observations read from the data set WORK.FUS_CLIPOT_DREAP.
    NOTE: The data set WORK.TABLE_POUR_HASH has 317124 observations and 3 variables.
    NOTE: Compressing data set WORK.TABLE_POUR_HASH increased size by 28.50 percent. 
          Compressed is 2426 pages; un-compressed would require 1888 pages.
    NOTE: L'étape DATA used (Total process time):
          real time           0.18 secondes
          cpu time            0.18 secondes
    Extrait de Résultat :

    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
     
     
    14814	124150319	1
    14814	178040920	2
    14814	753052522	3
    27835	981328900	4
    33215	108048911	5
    59315	96092617	6
    85031	799322987	7
    215817	115730429	8
    215817	315326243	9
    300054	901389050	10
    300405	6341406	11
    300851	189378210	12
    301423	746315154	13
    Deuxième 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
     
    22         
    23         DATA PseudoFamille;
    24         SET TABLE_POUR_HASH;
    25         Length IdClient $10.;
    26         IdClient=IdClient1;OUTPUT;
    27         IdClient=IdClient2;OUTPUT;
    28         KEEP IdCLient PseudoFamille;
    29         run;
     
    NOTE: Numeric values have been converted to character values at the places given by: (Line):(Column).
          26:10   27:10   
    NOTE: There were 317124 observations read from the data set WORK.TABLE_POUR_HASH.
    NOTE: The data set WORK.PSEUDOFAMILLE has 634248 observations and 2 variables.
    NOTE: Compressing data set WORK.PSEUDOFAMILLE increased size by 91.30 percent. 
          Compressed is 3916 pages; un-compressed would require 2047 pages.
    NOTE: L'étape DATA used (Total process time):
          real time           0.21 secondes
          cpu time            0.21 secondes

    Extrait de résultat :

    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
     
    PseudoF  IdClient
    1	14814
    1	124150319
    2	14814
    2	178040920
    3	14814
    3	753052522
    4	27835
    4	981328900
    5	33215
    5	108048911
    6	59315
    6	96092617
    7	85031
    Le data _Null_

    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
     
     
    NOTE: There were 634248 observations read from the data set WORK.PSEUDOFAMILLE.
    NOTE: There were 634248 observations read from the data set WORK.PSEUDOFAMILLE.
    NOTE: The data set WORK.FAMILLE has 294029 observations and 2 variables.
    NOTE: Compressing data set WORK.FAMILLE increased size by 44.78 percent. 
          Compressed is 2108 pages; un-compressed would require 1456 pages.
    NOTE: There were 634248 observations read from the data set WORK.PSEUDOFAMILLE.
    NOTE: L'étape DATA used (Total process time):
          real time           3.13 secondes
          cpu time            3.13 secondes
     
     
    124        
    125        proc sort DATA=famille;
    126        by VFamille;
    127        run;
     
    NOTE: There were 294029 observations read from the data set WORK.FAMILLE.
    NOTE: The data set WORK.FAMILLE has 294029 observations and 2 variables.
    NOTE: Compressing data set WORK.FAMILLE increased size by 44.78 percent. 
          Compressed is 2108 pages; un-compressed would require 1456 pages.
    NOTE: PROCEDURE SORT used (Total process time):
          real time           0.20 secondes
    4                                                          Le Système SAS                                08:08 Monday, June 16, 2014
     
          cpu time            0.20 secondes
    Ne connaissant pas vraiment le Hash, je ne saurais hélàs le "débugger"

  17. #17
    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
    Je ne peux pas te dire comme ça,

    il faudrait déjà regarder si cela ne viens pas des données par ce que sinon le code semble marcher sur mes deux exemples.

    Par exemple
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    DATA TABLE_POUR_HASH;
    SET FUS_CLIPOT_DREAP;
    length PseudoFamille $3. ;
    PseudoFamille=_n_;
    RENAME no_seq_cli=IdClient1;
    RENAME no_seq_cli1=IdClient2;
    run;
    peut-être ce serait mieux déjà avec length PseudoFamille $6. pour ton cas (moi j'avais mis 3 car je n'avais qu'une quinzaine de pseudo familles dans l'exemple).

    Donc

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    DATA TABLE_POUR_HASH;
     SET FUS_CLIPOT_DREAP;
     length PseudoFamille $6. ;
     PseudoFamille=STRIP(_n_);
     RENAME no_seq_cli=IdClient1;
     RENAME no_seq_cli1=IdClient2;
     run;
    et en rajoutant PseudoFamille=STRIP(_n_); pour faire plus propre...

    et dans ce cas dans la data _null_ tu remplace length VFamille $8. par length VFamille $6. pour être cohérent.

    De soirte à éviter d'avoir des pseudo familles tronquées donc, car ça pourrait expliquer la formation non voulue de "super familles" qui finiraient par s'agréger en une seule. Regarde de ce côté là.

  18. #18
    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
    Si tu veux comprendre le code et trouver un éventuel bug ci-joint un programme modifié sur "Charles" & "Amédée"

    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
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    DATA pseudoFamille;
    INFILE datalines;
    length IdClient $15. PseudoFamille $8. ;
    Input IdClient $ PseudoFamille $;
    datalines;
    Charles A
    Marie A
    Julie A
    Celestine B
    Xavier B
    Karl B
    Xavier C
    Pierre-Henri C
    Sophie C
    Pierre D
    Marie D
    Celestine D
    Amédée E
    Laurence E
    Clémence E
    ;
    run;
     
     
     
    DATA _null_;
    SET pseudoFamille end=eof;
    length VFamille $8. ;
    IF _n_=1 then 	do;
     
    DECLARE HASH Client (DATASET:"PseudoFamille",multidata:"YES");
    Client.DefineKey("IdClient" );
    Client.DefineData("IdCLient",'PseudoFamille');
    Client.DefineDone();
     
     
    DECLARE HASH PSF (DATASET:"PseudoFamille",multidata:"YES");
    PSF.DefineKey("PseudoFamille" );
    PSF.DefineData("PseudoFamille","IdClient");
    PSF.DefineDone();
     
     
    DECLARE HASH LISTE (multidata:"NO");
    LISTE = _NEW_ HASH();
    LISTE.DefineKey('PseudoFamille');
    LISTE.DefineDone();
    DECLARE HITER HLISTE("LISTE");
     
     
    DECLARE HASH NFAM (multidata:"NO");
    NFAM = _NEW_ HASH();
    NFAM.DefineKey('IdClient');
    NFAM.DefineData('IdCLient','VFamille');
    NFAM.DefineDone();
    DECLARE HITER HNFAM("NFAM");
     
     
    DECLARE HASH FAMILLE (multidata:"NO");
    FAMILLE = _NEW_ HASH();
    FAMILLE.DefineKey('IdClient');
    FAMILLE.DefineData("IdClient","VFamille");
    FAMILLE.DefineDone();
     
     
     
    				end;
     
    RC_FAMILLE=FAMILLE.FIND();
    IF RC_FAMILLE^=0	THEN	DO; /***si RC_Famille^=0 on a trouvé un chef de famille ***/
    	PUT "+++++++++++++";
    	PUT " ";
    	PUT ">>>>>>>>>> Un Chef de Famille a été trouvé, il s agit de l individu :" IDClient= ;
    	RC_NFam=NFam.Clear();
    	RC_Liste=Liste.Clear();
    	VFamille=PseudoFamille; /** l'identifiant de famille est le premier identifiant de pseudofamille du chef de famille **/
    	PUT "Le numero de la nouvelle famille est celui de la pseudofamille " PseudoFamille= ;
    	RC_NFAM=NFAM.ADD(); /** le chef de famille est le premier individu de sa famille **/
     
    	Test=1;
     
    		DO UNTIL (Test=0);
    PUT " ";
     PUT VFamille=  "------->Recherche des parentées<-------";
    		Test1=0;Test2=0;
    			RC_HNFAM=HNFAM.First();
    				DO UNTIL (RC_HNFAM^=0);
    					PUT " ";
    					PUT "Recherche des parentées de l individu " IDClient= ;
    					ctr=0;
    					RC_Client=Client.Find();
    						DO UNTIL (RC_Client^=0);
    							RC_Liste=Liste.Find();
    							IF RC_Liste^=0 THEN DO;RC_Liste=Liste.ADD(); ctr=1;PUT ">>>>>>>>>> La pseudo famille " PseudoFamille= " a été trouvée comme nouvelle famille parente";Test1=1;END;
    							RC_Client=Client.Find_Next();
    						END;
    					IF ctr=0 THEN PUT ">>>>>>>>>> RAS";
    				RC_HNFAM=HNFAM.Next();
    				END;
     
    			RC_HListe=HListe.First();
    					PUT " ";
    					PUT "Recherche de membres des parentées";
    				DO UNTIL (RC_HListe^=0);
    					PUT "Recherche parmi les membres de la pseudo famille parente" PseudoFamille= ;
    					ctr=0;
    					RC_PSF=PSF.Find();
    						DO UNTIL (RC_PSF^=0);
    							RC_NFAM=NFAM.Find();
    							IF RC_NFAM^=0 THEN DO;RC_NFAM=NFAM.ADD();PUT ">>>>>>>>>>  L individu " IdClient= "a été trouvé comme nouveau membre de la famille" ;Test2=1;ctr=1;END;
    							RC_PSF=PSF.Find_Next();
    						END;
    					IF ctr=0 THEN PUT ">>>>>>>>>> RAS";
    				RC_HListe=HListe.Next();
    				END;
     
    test=MAX(test1,test2);
    PUT " ";
     if test=0 then PUT ">>>>>>>>>> Aucun nouvel individu , ni aucune nouvelle pseudoFamille n ont été trouvées , la famille est complète";
     ELSE PUT ">>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va être effectuée";
     
    		END;
     PUT " ";
     PUT " ";
    PUT "$$$$$$$ L identification de la famille " VFamille= " est terminée";
    PUT "-----------------";
    PUT "$$$$$$$ Liste des membres";
    RC_HNFAM=HNFAM.First();
    DO UNTIL (RC_HNFAM^=0);
    RC_FAMILLE=FAMILLE.ADD();
    PUT "$$$$$$$ " IDClient= " est membre de la famille " VFamille=;
    RC_HNFAM=HNFAM.Next();
    END;
     
    						END;
     
    IF eof then DO;PUT " ";PUT " ";PUT " "; PUT " ";PUT "Identification des familles terminée, le résultat est placé dans la table Famille";RC=FAMILLE.OUTPUT(dataset:'FAMILLE');END;
     
     
    run;
     
     
    proc print DATA=famille;run;
     
     
    proc print data=pseudoFamille;run;

    Avec le déroulement des boucles dans la log

    +++++++++++++

    >>>>>>>>>> Un Chef de Famille a été trouvé, il s agit de l individu :IdClient=Charles
    Le numero de la nouvelle famille est celui de la pseudofamille PseudoFamille=A

    VFamille=A ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Charles
    >>>>>>>>>> La pseudo famille PseudoFamille=A a été trouvée comme nouvelle famille parente

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=A
    >>>>>>>>>> L individu IdClient=Marie a été trouvé comme nouveau membre de la famille
    >>>>>>>>>> L individu IdClient=Julie a été trouvé comme nouveau membre de la famille

    >>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va
    être effectuée

    VFamille=A ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Julie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Charles
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Marie
    >>>>>>>>>> La pseudo famille PseudoFamille=D a été trouvée comme nouvelle famille parente

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=A
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=D
    >>>>>>>>>> L individu IdClient=Pierre a été trouvé comme nouveau membre de la famille
    >>>>>>>>>> L individu IdClient=Celestine a été trouvé comme nouveau membre de la famille

    >>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va
    être effectuée

    VFamille=A ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Celestine
    >>>>>>>>>> La pseudo famille PseudoFamille=B a été trouvée comme nouvelle famille parente

    Recherche des parentées de l individu IdClient=Julie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Charles
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Marie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Pierre
    >>>>>>>>>> RAS

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=A
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=B
    >>>>>>>>>> L individu IdClient=Xavier a été trouvé comme nouveau membre de la famille
    >>>>>>>>>> L individu IdClient=Karl a été trouvé comme nouveau membre de la famille
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=D
    >>>>>>>>>> RAS

    >>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va
    être effectuée

    VFamille=A ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Celestine
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Karl
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Julie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Xavier
    >>>>>>>>>> La pseudo famille PseudoFamille=C a été trouvée comme nouvelle famille parente

    Recherche des parentées de l individu IdClient=Charles
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Marie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Pierre
    >>>>>>>>>> RAS

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=A
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=C
    >>>>>>>>>> L individu IdClient=Pierre-Henri a été trouvé comme nouveau membre de la famille
    >>>>>>>>>> L individu IdClient=Sophie a été trouvé comme nouveau membre de la famille
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=B
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=D
    >>>>>>>>>> RAS

    >>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va
    être effectuée

    VFamille=A ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Celestine
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Karl
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Julie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Pierre-Henri
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Xavier
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Sophie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Charles
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Marie
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Pierre
    >>>>>>>>>> RAS

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=A
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=C
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=B
    >>>>>>>>>> RAS
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=D
    >>>>>>>>>> RAS

    >>>>>>>>>> Aucun nouvel individu , ni aucune nouvelle pseudoFamille n ont été trouvées , la famill
    e est complète


    $$$$$$$ L identification de la famille VFamille=A est terminée
    -----------------
    $$$$$$$ Liste des membres
    $$$$$$$ IdClient=Celestine est membre de la famille VFamille=A
    $$$$$$$ IdClient=Karl est membre de la famille VFamille=A
    $$$$$$$ IdClient=Julie est membre de la famille VFamille=A
    $$$$$$$ IdClient=Pierre-Henri est membre de la famille VFamille=A
    $$$$$$$ IdClient=Xavier est membre de la famille VFamille=A
    $$$$$$$ IdClient=Sophie est membre de la famille VFamille=A
    $$$$$$$ IdClient=Charles est membre de la famille VFamille=A
    $$$$$$$ IdClient=Marie est membre de la famille VFamille=A
    $$$$$$$ IdClient=Pierre est membre de la famille VFamille=A
    +++++++++++++

    >>>>>>>>>> Un Chef de Famille a été trouvé, il s agit de l individu :IdClient=Amédée
    Le numero de la nouvelle famille est celui de la pseudofamille PseudoFamille=E

    VFamille=E ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Amédée
    >>>>>>>>>> La pseudo famille PseudoFamille=E a été trouvée comme nouvelle famille parente

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=E
    >>>>>>>>>> L individu IdClient=Laurence a été trouvé comme nouveau membre de la famille
    >>>>>>>>>> L individu IdClient=Clémence a été trouvé comme nouveau membre de la famille

    >>>>>>>>>> De nouvelles parentées ont été trouvées, une nouvelle recherche complète de parentée va
    être effectuée

    VFamille=E ------->Recherche des parentées<-------

    Recherche des parentées de l individu IdClient=Laurence
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Clémence
    >>>>>>>>>> RAS

    Recherche des parentées de l individu IdClient=Amédée
    >>>>>>>>>> RAS

    Recherche de membres des parentées
    Recherche parmi les membres de la pseudo famille parentePseudoFamille=E
    >>>>>>>>>> RAS

    >>>>>>>>>> Aucun nouvel individu , ni aucune nouvelle pseudoFamille n ont été trouvées , la famill
    e est complète


    $$$$$$$ L identification de la famille VFamille=E est terminée
    -----------------
    $$$$$$$ Liste des membres
    $$$$$$$ IdClient=Laurence est membre de la famille VFamille=E
    $$$$$$$ IdClient=Clémence est membre de la famille VFamille=E
    $$$$$$$ IdClient=Amédée est membre de la famille VFamille=E




    Identification des familles terminée, le résultat est placé dans la table Famille

  19. #19
    Membre actif
    Femme Profil pro
    Analyste en Intelligence d'Affaires (BI)
    Inscrit en
    Avril 2008
    Messages
    245
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste en Intelligence d'Affaires (BI)
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2008
    Messages : 245
    Points : 290
    Points
    290
    Par défaut Génial !!!!
    T'es un champion Jérôme, tu devances même mes prochaines questions lol!

    Car il va falloir que j'explique le programme à mon client et tu viens de le faire

    Concernant le programme, il FONCTIONNE PARFAITEMENT...j'attendais de finir l'intégralité de mon projet pour savourer la victoire

    Finalement, c'était bien la longueur le problème, j'ai opté pour des LENGHT à 8. donc je reste en numérique.

    Programme intégral de traitement
    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
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269
    270
    271
    272
    273
    274
    275
    276
    277
    278
    279
    280
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
     
    options missing=0;
     
     
    /************************      Traitements des tables issues des 8 conditions  de sélection des clients en doubles    ********************************/
     
    %MACRO traitement_ajout_cpt (lib=, tab=);
     
    /*SUPPRESSION DES DOUBLONS*/
     
    proc sort data=&lib..&tab. nodupkey out=&tab.;
    by no_seq_cli no_seq_cli1;
    run;
     
    /*VERIFICATION DE PRESENCE DE DOUBLON PAR CLIENT DANS L'OPTIQUE DE LA FUSION*/
     
    proc sort data=&tab. nodupkey out=t_&tab.(keep=no_seq_cli SOURCE_CDT) ;
    by no_seq_cli;
    run;
     
     
    /*FUSION*/
     
    data  t2_&tab.(keep=no_seq_cli1 /*compteur*/ SOURCE_CDT rename=(no_seq_cli1=no_seq_cli));
         merge t_&tab.(in=a)
                 &tab.(in=b);
    by no_seq_cli;
    if a and b;
    if no_seq_cli = no_seq_cli1 then delete;
    run; 
     
    /*FUSION TABLES POUR APPARIEMENT DES COUPLES*/
     
    PROC SQL;
    CREATE TABLE WORK.APPEND_&tab. AS 
    SELECT * FROM WORK.t_&tab.
     OUTER UNION CORR 
    SELECT * FROM WORK.t2_&tab.
    ;
    Quit;
     
    PROC SQL;
       CREATE TABLE WORK.F_&tab. AS 
       SELECT t1.NO_SEQ_CLI LABEL="NO_SEQ_CLI_BEN" AS NO_SEQ_CLI_BEN, 
    		  t1.SOURCE_CDT
          FROM WORK.APPEND_&tab.  t1
          ORDER BY t1.NO_SEQ_CLI;
    QUIT;
     
     
    PROC DATASETS lib=work nolist;
    DELETE &tab. t_&tab.  t2_&tab. APPEND_&tab.;
    RUN;
     
    PROC SORT DATA=F_&tab. (rename=SOURCE_CDT=CDT_&tab.);
    BY NO_SEQ_CLI_BEN;
    RUN;
     
    %MEND;
     
    %traitement_ajout_cpt(lib=sortie, tab=clipot_egal);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_soundex);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_difference);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_inclusion);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_inversion);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_appellation);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_sexediff);
    %traitement_ajout_cpt(lib=sortie, tab=clipot_ncinverse);
     
    /*CRÉATION DE L'INDICATEUR QUI SOULIGNE LA ou LES CONDITION DE DÉTECTION*/
     
    data CDT_CLIPOT_DREAP(keep=NO_SEQ_CLI_BEN CDT_DETECTION);
         merge F_CLIPOT_EGAL       (in=a)
               F_CLIPOT_SOUNDEX    (in=b)
    		   F_CLIPOT_DIFFERENCE (in=c)
    		   F_CLIPOT_INCLUSION  (in=d)
     		   F_CLIPOT_INVERSION  (in=e)
    		   F_CLIPOT_APPELLATION(in=f)
    		   F_CLIPOT_SEXEDIFF   (in=g)
    		   F_CLIPOT_NCINVERSE  (in=h);
     
         by no_seq_cli_ben ;
    	 cdt_detection=compbl(CDT_clipot_egal !! " " !! CDT_clipot_soundex !! " " !! CDT_clipot_difference !! " " !! 
    						  CDT_clipot_inclusion !! " " !! CDT_clipot_inversion !! " " !! CDT_clipot_appellation 
    						  !! " " !! CDT_clipot_sexediff!! " " !! CDT_clipot_ncinverse );
     
    RUN;
     
    proc sort data=CDT_CLIPOT_DREAP nodupkey out=SORTIE.CDT_CLIPOT_DREAP ;
    by no_seq_cli_ben cdt_detection;
    run;
     
     
    /*CRÉATION D'UNE TABLE UNIQUE DRÉAP PAR FUSION DES 8 TABLES*/
     
    proc sort data=sortie.clipot_egal nodupkey out=EGAL(keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_SOUNDEX nodupkey out=SOUNDEX(keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_DIFFERENCE nodupkey out=DIFFERENCE(keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_INCLUSION nodupkey out=INCLUSION(keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_INVERSION nodupkey out=INVERSION (keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_APPELLATION nodupkey out=APPELLATION (keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_SEXEDIFF nodupkey out=SEXEDIFF (keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
     
    proc sort data=sortie.clipot_NCINVERSE nodupkey out=NCINVERSE (keep=NO_SEQ_CLI NO_SEQ_CLI1 );
    by no_seq_cli no_seq_cli1;
    run;
    /*FUSION DE LA TABLE: ELLE RERESENTE CHACUN DES COUPLES DE CLIPOT*/
     
    data FUS_CLIPOT_DREAP (keep=NO_SEQ_CLI NO_SEQ_CLI1 );
         merge EGAL        (in=a)
               SOUNDEX     (in=b)
    		   DIFFERENCE  (in=c)
    		   INCLUSION   (in=d)
    		   INVERSION   (in=e)
    		   APPELLATION (in=f)
    		   SEXEDIFF    (in=g)
    		   NCINVERSE   (in=h);
         by NO_SEQ_CLI NO_SEQ_CLI1 ;
    RUN;
     
    /*SUPPRESSION DES DOUBLONS*/
     
    proc sort data=FUS_CLIPOT_DREAP nodupkey out=FUS_CLIPOT_DREAP;
    by no_seq_cli no_seq_cli1;
    run;
     
    /*TRAITEMENT HASH ---- APPARIEMENT DES FAMILLES*/
     
     
    DATA TABLE_POUR_HASH; 
    SET FUS_CLIPOT_DREAP;
    length PseudoFamille 8. ;
    PseudoFamille=STRIP(_n_);
    Rename no_seq_cli=IdClient1;
    Rename no_seq_cli1=IdClient2;
    run;
     
    DATA PseudoFamille;
    SET TABLE_POUR_HASH;
    Length IdClient 8.;
    IdClient=IdClient1;OUTPUT;
    IdClient=IdClient2;OUTPUT;
    KEEP IdCLient PseudoFamille;
    run;
     
    DATA _null_;
    SET pseudoFamille end=eof;
    length VFamille 8. ;
    IF _n_=1 then 	do;
     
    DECLARE HASH Client (DATASET:"PseudoFamille",multidata:"YES");
    Client.DefineKey("IdClient" );
    Client.DefineData("IdCLient",'PseudoFamille');
    Client.DefineDone();
     
     
    DECLARE HASH PSF (DATASET:"PseudoFamille",multidata:"YES");
    PSF.DefineKey("PseudoFamille" );
    PSF.DefineData("PseudoFamille","IdClient");
    PSF.DefineDone();
     
     
    DECLARE HASH LISTE (multidata:"NO");
    LISTE = _NEW_ HASH();
    LISTE.DefineKey('PseudoFamille');
    LISTE.DefineDone();
    DECLARE HITER HLISTE("LISTE");
     
     
    DECLARE HASH NFAM (multidata:"NO");
    NFAM = _NEW_ HASH();
    NFAM.DefineKey('IdClient');
    NFAM.DefineData('IdCLient','VFamille');
    NFAM.DefineDone();
    DECLARE HITER HNFAM("NFAM");
     
     
    DECLARE HASH FAMILLE (multidata:"NO");
    FAMILLE = _NEW_ HASH();
    FAMILLE.DefineKey('IdClient');
    FAMILLE.DefineData("IdClient","VFamille");
    FAMILLE.DefineDone();
     
     
     
    				end;
     
    RC_FAMILLE=FAMILLE.FIND();
    IF RC_FAMILLE^=0	THEN	DO; /***si RC_Famille^=0 on a trouvé un chef de famille ***/
    	RC_NFam=NFam.Clear();
    	RC_Liste=Liste.Clear();
    	VFamille=PseudoFamille; /** l'identifiant de famille est le premier identifiant de pseudofamille du chef de famille **/
    	RC_NFAM=NFAM.ADD(); /** le chef de famille est le premier individu de sa famille **/
    	Test=1;
     
    		DO UNTIL (Test=0);
     
    		Test1=0;Test2=0;
    			RC_HNFAM=HNFAM.First();
    				DO UNTIL (RC_HNFAM^=0);
    					RC_Client=Client.Find();
    						DO UNTIL (RC_Client^=0);
    							RC_Liste=Liste.Find();
    							IF RC_Liste^=0 THEN DO;RC_Liste=Liste.ADD(); Test1=1;END;
    							RC_Client=Client.Find_Next();
    						END;
    				RC_HNFAM=HNFAM.Next();
    				END;
     
    			RC_HListe=HListe.First();
    				DO UNTIL (RC_HListe^=0);
    					RC_PSF=PSF.Find();
    						DO UNTIL (RC_PSF^=0);
    							RC_NFAM=NFAM.Find();
    							IF RC_NFAM^=0 THEN DO;RC_NFAM=NFAM.ADD();Test2=1;END;
    							RC_PSF=PSF.Find_Next();
    						END;
    				RC_HListe=HListe.Next();
    				END;
     
    test=MAX(test1,test2);
     
     
    		END;
     
     
    RC_HNFAM=HNFAM.First();
    DO UNTIL (RC_HNFAM^=0);
    RC_FAMILLE=FAMILLE.ADD();
    RC_HNFAM=HNFAM.Next();
    END;
     
    						END;
     
    IF eof then RC=FAMILLE.OUTPUT(dataset:'FAMILLE');
     
     
    run;
     
    proc sort DATA=famille;
    by VFamille;
    run;
     
    /*******************************VERIFIER QUE LE RESULTAT EST 0 OBSERVATIONS****************************************/
    proc sql;
    create table Compteurs_restants as select
    distinct a.*,
    		 count (VFamille) as test_ID
    from famille as a
    group by VFamille 
    Having test_ID=1;
    Quit;
     
    /*TABLE DREAP FINAL*/
     
    proc sql;
    create table sortie.clipot_dreap as select
    distinct a.IDclient as NO_SEQ_CLI_BEN,
    		 a.VFamille AS compteur_dreap,
    		 count (VFamille) as Nombre_occurence_cpt,
    		 1 as DREAP
    from famille as a
    group by VFamille;
    Quit;
     
    /* SUPPRESSION DES TABLES INUTILES POUR LA SUITE*/
     
    PROC DATASETS lib=work nolist;
    DELETE  CDT_CLIPOT_DREAP 
    		EGAL SOUNDEX DIFFERENCE INCLUSION INVERSION APPELLATION SEXEDIFF NCINVERSE
    		F_CLIPOT_EGAL F_CLIPOT_SOUNDEX F_CLIPOT_DIFFERENCE F_CLIPOT_INVERSION 
    		F_CLIPOT_INCLUSION F_CLIPOT_APPELLATION F_CLIPOT_SEXEDIFF F_CLIPOT_NCINVERSE
    		F_CLIPOT_DREAP_SEL  F_CLIPOT_DREAP_FREQSSDOUB F_CLIPOT_DREAP_FREQ doublons 
    		;
    RUN;
    J'ai le coeur léger !!!!

    Merci beaucoup !

  20. #20
    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
    Merci ,

    en tout cas le problème à résoudre est facile d'énonciation, et la solution sous forme de traitement à base d'objets HASH est je trouve un bon exercice pour celui qui souhaite s'y initier.

    N'oublie pas d'avertir ton commanditaire (c'est cela en quoi la solution n'est pas forcément entièrement satisfaisante) que ça ne marchera pas avec des bases de toutes tailles, mais uniquement celles qui seront compatible avec l'espace de mémoire vive réservé à SAS disponible sur la machine.

    Bon courage pour la suite.

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/06/2010, 14h28
  2. [HTML 4.0] regrouper des image pour quelle soit une seule
    Par nostalamigo dans le forum Balisage (X)HTML et validation W3C
    Réponses: 3
    Dernier message: 05/04/2009, 15h47
  3. [PHP 4] Recuperer des données au sein d'une page HTML
    Par gilles974 dans le forum Langage
    Réponses: 1
    Dernier message: 10/03/2009, 09h36
  4. probleme de changement des panel au sein d'une fenetre
    Par switch1 dans le forum Composants
    Réponses: 2
    Dernier message: 04/03/2009, 13h17

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