BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Hansi_12345
Fluorite | Level 6

Hallo liebes Forum,

 

ich habe folgendes Problem:

 

ich habe eine Makro-Variable "Monat" definiert, die die Werte 1-3 enthalten kann. Außerdem habe ich eine Datei, die Werte enthält.

Jetzt möchte ich, dass bestimmte Dinge passieren, je nachdem, welcher Wert der Variable Monat vorher zugewiesen wurde.

 

So wäre mein Vorgehen jetzt gewesen:

 

%let Monat = 3;

data work.test;

     set work.test;

     if &Monat = 1 then do;

            Jan_multi=Jan*1;

            drop Jan;

     end;

     else if &Monat = 2 then do;

            Jan_multi= Jan*1;

            Feb_multi= Feb*2;

            drop Jan Feb;

     end;

     else if &Monat = 3 then do;

           Feb_multi= Feb*2;

           Mrz_multi= Mrz*3;

           drop Jan Feb Mrz;

     end;

     else do;

           test=Jan;

     end;

run;

 

Das Problem ist jetzt, dass der letzte Schritt, also die else do-Anweisung überflüssigerweise auch durchgeführt wird, obwohl ich oben ja nur die 3 angegeben habe. Also es wird auch eine Spalte test angelegt, die die Werte aus der Spalte Jan enthält, obwohl das nicht passieren sollte. Das macht in meinen Augen gar keinen Sinn... Woran liegt das denn, bzw. wie kann ich das verhindern?

 

Vielen Dank schon mal und freundliche Grüße

1 ACCEPTED SOLUTION

Accepted Solutions
FreelanceReinh
Jade | Level 19

Hallo @Hansi_12345 und willkommen in den SAS Support Communities,

 

[Switching to English now, sorry! :-)] If you want to create datasets of different structures (like having different sets of variables) depending on the value of a macro variable, you will need to use code generation techniques such as the SAS macro language.

 

Here is an example based on your code:

 

data work.have;
Jan=4; Feb=7; Mrz=13;
run;

%macro multi(Monat=, in=work.have, out=work.want);

  data &out;
  set ∈
  %if &Monat = 1 %then %do;
    Jan_multi=Jan*1;
    drop Jan;
  %end;
  %else %if &Monat = 2 %then %do;
    Jan_multi= Jan*1;
    Feb_multi= Feb*2;
    drop Jan Feb;
  %end;
  %else %if &Monat = 3 %then %do;
    Feb_multi= Feb*2;
    Mrz_multi= Mrz*3;
    drop Jan Feb Mrz;
  %end;
  %else test=Jan;;
  run;

%mend multi;

%multi(Monat=1, out=work.want1)
%multi(Monat=2, out=work.want2)
%multi(Monat=3, out=work.want3)
%multi(Monat=0, out=work.want0)

Each of the four macro calls (%multi(Monat=1, out=work.want1), etc.) creates a new dataset from work.have and the four "want..." datasets have different structures.

 

 


@Hansi_12345 wrote:

Also es wird auch eine Spalte test angelegt, die die Werte aus der Spalte Jan enthält, obwohl das nicht passieren sollte.


If variable test is not contained in the input dataset (work.test) and the final ELSE branch is not executed (because macro variable Monat has one of the three values 1, 2 or 3), variable test will be created (as Rick has explained), but it will only contain missing values. Most likely you were looking at a version of work.test that already contained variable test from a previous run of your data step with a different value of Monat. You should better avoid this pitfall by naming input and output datasets differently (as opposed to overwriting the input dataset with the output dataset), e.g.

 

data test1;
set test;
...

 

 

PS: Do you know the nice subforum CoDe SAS? That's a great place for discussing SAS questions like yours in German.

View solution in original post

4 REPLIES 4
Rick_SAS
SAS Super FREQ

SAS scans the program for any variables it needs to create and creates them all at the start of the program. Run the program to see that Y, Z, and TEST are all created, but not always assigned:

 

data test;
input x @@;
datalines;
1 2 1 2 1 2 2 2
;

data A;
set test;
if x = 1 then
   y = 1;
else if x=2 then
   z = 2;
else 
   test = 3;
run;

proc print; run;

Also, the DROP statement is global. It doesn't make sense to use it inside an IF-THEN/ELSE block.

 

FreelanceReinh
Jade | Level 19

Hallo @Hansi_12345 und willkommen in den SAS Support Communities,

 

[Switching to English now, sorry! :-)] If you want to create datasets of different structures (like having different sets of variables) depending on the value of a macro variable, you will need to use code generation techniques such as the SAS macro language.

 

Here is an example based on your code:

 

data work.have;
Jan=4; Feb=7; Mrz=13;
run;

%macro multi(Monat=, in=work.have, out=work.want);

  data &out;
  set ∈
  %if &Monat = 1 %then %do;
    Jan_multi=Jan*1;
    drop Jan;
  %end;
  %else %if &Monat = 2 %then %do;
    Jan_multi= Jan*1;
    Feb_multi= Feb*2;
    drop Jan Feb;
  %end;
  %else %if &Monat = 3 %then %do;
    Feb_multi= Feb*2;
    Mrz_multi= Mrz*3;
    drop Jan Feb Mrz;
  %end;
  %else test=Jan;;
  run;

%mend multi;

%multi(Monat=1, out=work.want1)
%multi(Monat=2, out=work.want2)
%multi(Monat=3, out=work.want3)
%multi(Monat=0, out=work.want0)

Each of the four macro calls (%multi(Monat=1, out=work.want1), etc.) creates a new dataset from work.have and the four "want..." datasets have different structures.

 

 


@Hansi_12345 wrote:

Also es wird auch eine Spalte test angelegt, die die Werte aus der Spalte Jan enthält, obwohl das nicht passieren sollte.


If variable test is not contained in the input dataset (work.test) and the final ELSE branch is not executed (because macro variable Monat has one of the three values 1, 2 or 3), variable test will be created (as Rick has explained), but it will only contain missing values. Most likely you were looking at a version of work.test that already contained variable test from a previous run of your data step with a different value of Monat. You should better avoid this pitfall by naming input and output datasets differently (as opposed to overwriting the input dataset with the output dataset), e.g.

 

data test1;
set test;
...

 

 

PS: Do you know the nice subforum CoDe SAS? That's a great place for discussing SAS questions like yours in German.

Hansi_12345
Fluorite | Level 6
Thanks a lot for all your advices. You helped me a lot.
Kurt_Bremser
Super User

Ich würde den Makro noch massiv vereinfachen:

%macro mult(monat=,in=,out=);
%local monate i mm;
%let monate = JanFebMrzAprMaiJunJulAugSepOktNovDez;
data &out.;
set &in.;
%if &monat ge 1 and &monat. le 12
%then %do i = 1 %to &monat.;
  %let mm = %substr(&monate.,%eval((&i. - 1) * 3 + 1),3);
  &mm._multi = &mm. * &i.;
  drop &mm.;
%end;
%else %do;
  test = Jan;
%end;
run;
%mend;

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 4 replies
  • 648 views
  • 3 likes
  • 4 in conversation