简体   繁体   中英

SAS: How to reference a global macro variable to create new table or dataset?

I'm having some trouble referencing a global macro variable outside of the macro to create a new data set. The global variable was created to run a loop for creating several yearly data sets using a vector of specified years, as you can see in the code below:

%macro loopyear;
    %global year;
    %do year = 2004 %to 2017;

proc import datafile = "C:\Filepath\blah.txt"
    dbms = dlm out = blah&year.;  /*Creates a dataset for each year, e.g. blah2004, blah2005, etc.) */
    delimiter = " ";
    getnames = no;
run;

data blah&year.;
    set blah&year.;
    year = &year.;
run;

proc sql;
    create table blah&year._rail as 
        select year, var1, var2, var3, var4
        from blah&year.
        where var2= "rail";
quit;

    %end;
%mend loopyear;
%loopyear;

/*Merge all year datasets into one master set*/

data blah_total;
    set blah&year._rail;
run;

When I try to create the master data set outside of the macro, however, I get the following error:

data blah;
    set blah&year._rail;
run;
ERROR: File work.blah2018_rail.data does not exist

This is frustrating because I'm only trying to create the master set based on 2004-2017 data, as referenced in the macro variable. Can someone help me pinpoint my error -- is it in the way I defined the global variable, or am I missing a step somewhere? Any help is appreciated.

Thanks!

This is an interesting quirk of both macro and data step do-loops in SAS - the loop counter is incremented before the exit condition is checked, so after your loop has run it will be one increment past your stop value, eg:

%macro example;
  %do i = 1 %to 3;
    %put i = &i;
  %end;
  %put i = &i;  
%mend;
%example;

Output:

i = 1
i = 2
i = 3 
i = 4

For your final step you probably want the set statement to look like this:

set blah2004_rail ... blah2017_rail;

You could write a macro loop to generate the list and move the data step inside your macro, eg

set %do year = 2004 %to 2017; blah&year._rail %end;;

The second semi-colon is important! You need one to close the %end and one to terminate the set statement.

Change your naming structure. Have a common prefix and put the year at the end, then you can use the semi colon to short reference all the datasets at once.

%macro loopyear;
    %global year;
    %do year = 2004 %to 2017;

proc import datafile = "C:\Filepath\blah.txt"
    dbms = dlm out = blah&year.;  /*Creates a dataset for each year, e.g. blah2004, blah2005, etc.) */
    delimiter = " ";
    getnames = no;
run;

data blah&year.;
    set blah&year.;
    year = &year.;
run;

proc sql;
    create table blah_rail_&year. as 
        select year, var1, var2, var3, var4
        from blah&year.
        where var2= "rail";
quit;

    %end;
%mend loopyear;
%loopyear;

/*Merge all year datasets into one master set*/

data blah_total;
    set blah_rail: ;
run;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM