Eine Variable in mehrere aufteilen
Verfasst von bezNika am 28 Juli, 2010 - 14:27
Hallo,
gibt es eine Möglichkeit, eine Variable in mehrere aufzuteilen?
Beispiel: Variable d = 65347892, 62488329, 57349201 (in einem Datensatz)
d = 75134980, 483901ß5, 53478215, 7534820574 (im nächsten) = > die Länge der Variablen ist in allen Datensätzen unterschiedlich, die genaue maximale Länge wegen zu hoher Anzahl der Datensätze kann nicht bestimmt werden.
Nach dem Aufteilen sollen dann Variablen d1 = 65347892, d2 = 62488329 u.s.w. entstehen.
ich habe es mit folgendem Macro versucht, aber das Ergebnis ist nicht wie erwartet/erwünscht:
%macro KONTO;
%let i = 1;
%let dat = %scan(d00, &i., ',');
%do %while (%length(&dat.));
data PBKONTO;
set PBKONTO;
d01 = &dat.;
run;
%let i = %eval(&i.+1);
%let dat = %scan(d00, &i., ',');
%end;
%mend;
%konto;
%let i = 1;
%let dat = %scan(d00, &i., ',');
%do %while (%length(&dat.));
data PBKONTO;
set PBKONTO;
d01 = &dat.;
run;
%let i = %eval(&i.+1);
%let dat = %scan(d00, &i., ',');
%end;
%mend;
%konto;
Kann mir da jemand helfen?
Danke im Voraus!
»
- Anmelden oder Registrieren um Kommentare zu schreiben

Ich hoffe...
...ich habs richtig verstanden. Hallo Herr Schneider erstmal. Ich hab das ganze jetzt mal ohne Makro gelöst.
input d $50.;
datalines;
235148,568464321,231354
89845138,3548
879456321,86463,3234686,2130
231354
;
run;
data _null_;
set test end=ende;
if _N_ eq 1 then call execute('data test2;');
i = 1;
do while(scan(d, i, ',') ne '');
call execute('d' || compress(i) || '=' || compress(scan(d, i, ','))||';');
i = i+1;
end;
call execute('output;');
i = 1;
do while(scan(d, i, ',') ne '');
call execute('d' || compress(i) || '=.;');
i = i+1;
end;
if ende then call execute('run;');
run;
Meine Variante durchläuft die Quelltabelle test und baut sich mit call execute einen neuen Datastep zusammen. Die Variable d wird via scan in seine Einzelwerte zerlegt. Diese landen dann in automatisch erstellten Variablen in der neuen Tabelle test2.
Gruß Frederik
Noch eine Lösung mit etwas Makro
Hallo Herr Schneider, hallo Frederik,
anbei noch eine, zwar nicht so elegante Lösung, ohne call execute:
data _null_;
set test end=lastrec;
if _n_=1 then max=0;
retain max;
max=max(max,countc(d,',')+1);
if lastrec;
call symput('max',max);
run;
data test2(drop=d i);
set test;
array _d(1:&max.) d1-d%left(&max.);
do i = 1 to &max.;
_d(i)=.;
if scan(d,i,',') ne '' then _d(i)=scan(d,i,',');
end;
run;
@Frederik: Ich kenne mich mit call execute (leider noch) nicht aus. Gehe ich richtig davon aus,
dass das zweite do while im Prinzip die Initialisierung ist, die ich mit _d(i)=. mache?
Ich glaube ich muss mich mal damit beschäftigen.
Viele Grüße
Wolfgang
So ist es.
Hallo Wolfgang,
genau so ist es, die zweite while-Schleife ist zum "resetten" der Variablen.
Gruß Frederik
Hallo Wolfgang, hallo
Hallo Wolfgang, hallo Frederik.
Vielen Dank für beide Lösungen. Ich habe jetzt die zweite Lösung, mit arrays, benutzt, weil die Splatennamen dann entsprechend der Aufgabenstellung aussehen: d01, d02, ..., d10 (leider habe ich vergessen, es in der Aufgabenbeschreibung zu erwähnen).
Die andere Lösung mit call execute - Funktion war aber auch neu und daher sehr interessant für mich.
Nun habe ich gehofft, ich könnte aus den vorgeschlagenen Lösungen die Lösung für den zweiten Teil der Aufgabe selber ableiten, ledeir sieht es anders aus. Ich komme einfach nicht darauf, wie man den zweiten Teil lösen könnte.
In diesem Teil gibt es dann Variable d00k00, die den gleichen Aufbau/Struktur hat, wie die Variable d im ersten Teil ( 463178965413, 134895413, 7438901473). Bei bei der Aufteilung soll erstmal der index hinter dem k erhöht werden: d00k01, d00k02, d00k03...
bis d00k10, danach wird der index hinter d erhöht: d01k01, d01k02... etc.
Wäre es möglich, auch diese Aufgabe zu lösen?
Vielen Dank im Voraus!
Gruß,
Alex
Quick & ziemlich Dirty
Ich hab hier eine Lösung für dich. Ich gebe zu, sie ist hässlich. Aber was zählt, ist was HINTEN rauskommt, gell?
length d $100.;
d = "2344";
output;
d = "235148,568464321,231354";
output;
d = "34545,345345,3453455,6547,8786,9786,4564,345345,23423,43242,112,222,444";
output;
d="89845138,3548";
output;
run;
data _null_;
set test end=ende;
if _N_ eq 1 then call execute('data test2;');
dzaehler = -1;
kzaehler = 0;
internz = 1;
do while(dzaehler ge -1);
dzaehler = dzaehler+1;
do while(kzaehler ge 0);
if(kzaehler > 10) then do;
kzaehler = 0;
leave;
end;
zahl = scan(d, internz, ',');
if(zahl = '') then do;
kzaehler = 0;
dzaehler = -2;
leave;
end;
else do;
call execute('d' || compress(put(dzaehler,z2.)) || 'k' || compress(put(kzaehler,z2.)) || '=' || compress(zahl)||';');
kzaehler = kzaehler+1;
internz = internz+1;
end;
end;
end;
call execute('output;');
dzaehler = -1;
kzaehler = 0;
internz = 1;
do while(dzaehler ge -1);
dzaehler = dzaehler+1;
do while(kzaehler ge 0);
if(kzaehler > 10) then do;
kzaehler = 0;
leave;
end;
zahl = scan(d, internz, ',');
if(zahl = '') then do;
kzaehler = 0;
dzaehler = -2;
leave;
end;
else do;
call execute('d' || compress(put(dzaehler,z2.)) || 'k' || compress(put(kzaehler,z2.)) || '=.;');
kzaehler = kzaehler+1;
internz = internz+1;
end;
end;
end;
if ende then call execute('run;');
run;
Ich habe einfach eine zweite äußere Schleife zum Zählen eingebaut und noch die führende Null angefügt. Ach ja, und natürlich noch einen internen Zähler, um mir beim Erreichen der dxxk10 die Position zu merken.
Gruß Frederik
Hallo Frederik, es hat
Hallo Frederik,
es hat wunderbar geklappt: das Ergebnis wie erwartet, was im Hintergrund passiert, sieht sowieso keiner ;-)
Vielen, vielen Dank nochmal!
Gruß,
Alex