LesezeichenAbonnierenRSS-Feed abonnieren
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Spinner_Bernd
Calcite | Level 5

Hallo zusammen,

 

für eine Verteilung von Daten habe ich die Anforderung das eine Tabelle auf verschiedene Tabellen, deren Anzahl je nach enthaltenen Gruppen variieren kann, aufgeteilt werden muss.

Hier habe ich auch einen Code der funktioniert:

 data WORK.CLASS;
   infile datalines dsd truncover;
   input Name $9. Group $1.;
 datalines;
 Alfred  A 
 Alice   B 
 Barbara B 
 Carol   C 
 Henry   C 
 Paul    D 
;
 run;

 %MACRO gruppen(datei1, pool);
PROC SQL NOPRINT;
SELECT DISTINCT &pool INTO :pools SEPARATED BY ' '
FROM &datei1;
QUIT;

%DO i=1 %TO &SQLOBS;
%LET group=%SCAN(&pools, &i);
%PUT &i: *&group*;
proc sql noprint;
select distinct count(*) into :Menge TRIMMED from &datei1  where &pool = "&group" 
group by &pool;
quit;

proc sql;
create table &group._&Menge._Ende  as select * from &datei1  where &pool = "&group" ;
quit;

%END;
%MEND;
%gruppen(WORK.class, group);

nun mein Problem:

Wenn die Menge in den einzelnen Gruppen einen bestimmten Wert unterschreitet sollen diese Gruppen automatisch zu einer Tabelle zusammengefasst werden.

In den Beispieldaten oben sollten die gruppen A + D zu einer Tabelle zusammengefasst sein und die Gruppen B und C jeweils in einer eigenen Tabelle stehen.

 

Danke für eure Unterstützung!

Viele Grüße

Bernd

1 AKZEPTIERTE LÖSUNG

Akzeptierte Lösungen
andreas_lds
Jade | Level 19

Ein Vorschlag:

 data work.have;
   infile datalines dsd truncover;
   input Name $9. Group $1.;
 datalines;
 Alfred  A 
 Alice   B 
 Barbara B 
 Carol   C 
 Henry   C 
 Paul    D 
;

proc summary data=work.have nway;
   class Group;
   output out= work.Size(drop= _type_ rename=(_freq_=count));
run;

%global schwelle;
%let schwelle = 2;


data work.ReGroup;
   set work.Size end=jobDone;
   
   length 
      Dataset $ 42
      DatasetList $ 4200
   ;
   
   retain DatasetList;
   
   Dataset = catx('_', ifc(count < &schwelle., 'ZZZ', Group), Count, 'Ende');
   
   if index(DatasetList, trim(Dataset)) = 0 then DatasetList = catx(' ', DatasetList, Dataset);
   
   if jobDone then call symputx('datasetList', DatasetList);
   
   drop DatasetList;
run;

data _null_;
   set work.ReGroup end= jobDone;
   
   if _n_ = 1 then do;
      call execute(cat('data ', "&datasetList.", ';'));
      call execute('set work.have;');
      call execute('select (Group);');
   end;
   
   call execute(catx(' ', 'when (', quote(trim(Group)), ') output', Dataset, ';'));
   
   if jobDone then do;
      call execute('end; run;');
   end;
run;

Lösung in ursprünglichem Beitrag anzeigen

6 ANTWORTEN 6
FreelanceReinh
Jade | Level 19

Hallo @Spinner_Bernd,

 

in dem Beispiel liegt es nahe, die Gruppen A und D zusammenzufassen -- wenn man 2 als den "bestimmten Wert" annimmt, den die Gruppengrößen hier unterschreiten. Weniger eindeutig würde es aber schon, wenn nur ein weiterer Satz mit Group='D' hinzukäme. Dann müsste der Satz mit Group='A' einer der drei anderen Gruppen zugeschlagen werden. Aber welcher? Würde z. B. Gruppe C bevorzugt, wenn B und D bereits drei Sätze enthielten, C aber nur zwei? Was wäre, wenn es weitere Gruppen E, F, ..., Z mit je einem Satz gäbe? Allein auf Basis der Regel, mindestens zwei Sätze in einer Ausgabetabelle zu haben, könnte man diese alle zu einer großen Tabelle zusammenfassen. Ich vermute aber, dass andere, noch nicht genannte Regeln dagegensprechen.

 

Wie viele Sätze und wie viele Gruppen kann die aufzuteilende Tabelle enthalten? Wenn die Anzahlen hinreichend groß sind und unter vielen kombinatorisch möglichen Aufteilungen eine "optimale" gesucht ist (etwa eine möglichst "gleichmäßige"), könnten Methoden aus dem Modul SAS/OR erforderlich sein (das aber in meiner SAS-Lizenz nicht enthalten ist).

Spinner_Bernd
Calcite | Level 5

Hallo @FreelanceReinh 

die Ursprungstabelle ist variabel sie schwankt Erfahrungsgemäß zwischen 200 und 5000 Datensätzen und wird momentan auf bis zu 40 Gruppen aufgeteilt, um diese Anzahl zu reduzieren suche ich jetzt nach einer Lösung, die alle Kleinstmengen zu einer Gruppe zusammenfasst. Daher auch die Beispieldaten mit zwei Gruppen mit einem Datensatz und zwei Gruppen mit zwei Datensätzen.

 

Es soll nicht möglichst gleichmäßig aufgeteilt werden, sondern nach einem bestimmten Merkmal wird eine Gruppe gebildet und als seperate Tabelle gespeichert um dann in einem weiteren System weiterverarbeitet zu werden.

 

Viele Grüße

Bernd

andreas_lds
Jade | Level 19

Moin Bernd!

 

Da fehlen noch ein paar Kleinigkeiten in deiner Beschreibung:

  • Welcher Wert muss unterschritten werden, damit eine Gruppe mit einer anderen zusammengefasst wird?
  • Was soll passieren, wenn eine ungerade Anzahl von Gruppen diesen Wert unterschreitet?

 

Spinner_Bernd
Calcite | Level 5

Hallo Andreas,

 

es geht darum iKleinstmengen nach einer Aufteilung zusammenzufassen, in den Beispieldaten wäre das momentan 1 Datensatz, in den Realdaten wird es wohl auf einen Wert von 5-10 rauslaufen ( der Wert wird aber definitiv für alle Gruppen gleich sein)

Entscheidend ist nur die Menge in der einzelnen Gruppe um die Gruppe entweder seperat zu lassen oder zu einer Sammelgruppe zusammenzufassen

Alles unter Schwellwert => eine Sammeltabelle

Alles über dem Schwellwert => je Gruppe eine Tabelle

 

Viele Grüße

Bernd

andreas_lds
Jade | Level 19

Ein Vorschlag:

 data work.have;
   infile datalines dsd truncover;
   input Name $9. Group $1.;
 datalines;
 Alfred  A 
 Alice   B 
 Barbara B 
 Carol   C 
 Henry   C 
 Paul    D 
;

proc summary data=work.have nway;
   class Group;
   output out= work.Size(drop= _type_ rename=(_freq_=count));
run;

%global schwelle;
%let schwelle = 2;


data work.ReGroup;
   set work.Size end=jobDone;
   
   length 
      Dataset $ 42
      DatasetList $ 4200
   ;
   
   retain DatasetList;
   
   Dataset = catx('_', ifc(count < &schwelle., 'ZZZ', Group), Count, 'Ende');
   
   if index(DatasetList, trim(Dataset)) = 0 then DatasetList = catx(' ', DatasetList, Dataset);
   
   if jobDone then call symputx('datasetList', DatasetList);
   
   drop DatasetList;
run;

data _null_;
   set work.ReGroup end= jobDone;
   
   if _n_ = 1 then do;
      call execute(cat('data ', "&datasetList.", ';'));
      call execute('set work.have;');
      call execute('select (Group);');
   end;
   
   call execute(catx(' ', 'when (', quote(trim(Group)), ') output', Dataset, ';'));
   
   if jobDone then do;
      call execute('end; run;');
   end;
run;
Spinner_Bernd
Calcite | Level 5

Danke Andreas!

Dein Code macht genau das was ich wollte 😊