BookmarkSubscribeRSS Feed
hayely_bristine
Calcite | Level 5

Hey everyone!  I am new to macros, so bare with me please!  I have some program that produces some tables and plots for a certain dataset.  What I am trying to do is use a macro, so that I can enter a different dataset (same columns, just a different year) and then get the tables and plots for that dataset.  

 

For example, I have 7 data sets in my folder and what I would like to do is somehow rename each dataset Cars1, Cars2,...Cars7, and then I want to use a macro so I can type in "Cars4" into my code once, and then the tables and plots will be generated for the Cars4 data set.

 

Can anyone provide me with an example on how to do this?  Thanks!

 

%let weatherData = \\Client\C$\Math450\USC00010063.DLY;
DATA WEATHER;
  INFILE "&weatherData";
  INPUT Id  $  1-11 
        Year 12-15 
        Month 16-17 
        FEATURE $ 18-21 @22 (D1-D31)(5. +3);
RUN;

DATA TMIN TMAX;
  SET WEATHER;
  IF FEATURE ='TMIN' THEN OUTPUT TMIN;
  ELSE IF FEATURE ='TMAX' THEN OUTPUT TMAX;
  RUN;

  PROC FREQ DATA=TMAX;
  TABLES YEAR*Month/NOCOL NOROW NOPERCENT;
  RUN;

  PROC TRANSPOSE DATA=TMAX(DROP=id) OUT=LONG;
  BY Year Month;
  VAR D1-D31;
  RUN;

  PROC PRINT DATA=LONG;
  RUN;

  PROC SORT DATA=LONG;
  BY Year Month;
  RUN;

  DATA play;
  SET LONG;
  BY Year Month;
  IF first.Month THEN day=0;
  day+1;
  IF Month IN (4,6,9,11) & day=31 THEN DELETE;
  IF Month=2 & day>29 THEN DELETE;
  IF Month=2 & mod(Year,4)~=0 & day=29 THEN DELETE;
  RUN;

DATA play;
  SET play;
  tdate=MDY(Month,day,Year);
  FORMAT tdate mmddyy10.;
  RENAME COL1=TMAX;
  DROP _NAME_;
  RUN;

  DATA PLAY1;
  SET PLAY;
  TMAX1=.;
  IF (COL1 = -9999) THEN TMAX1 =.;
  RUN;

  PROC PRINT DATA=PLAY1;
  VAR Year Month Day Tdate TMAX1;
  RUN; 

  PROC SGPLOT DATA = PLAY;
  by Year;
  scatter x = month y = TMAX;
  RUN;
4 REPLIES 4
ballardw
Super User

Best would be to show your existing code. Then we know where and how many places you need to replace things like the data set name.

 

By "in a folder" do  you mean a SAS Library? That would be the SAS approach to managing data in shared storage location.

hayely_bristine
Calcite | Level 5

I edited the question and included my code!  Thanks so much for helping 🙂

ballardw
Super User

So, why are you removing dates from the last day of the month for just some months?

What is the magic number -9999? If it is an external value that should be missing then set it missing as early as practical.

 

And maybe a general description of what this code is supposed to do in narrative terms.

 

A few of general comments:

1) It is quite often better to separate out reading external data and generating reports. That way you can validate that your "raw" data is properly structured and has all the values you need before generating the report.

2) use of code like

DATA play;
  SET play;

inside a macro means that you may never know when something went "wrong" with code. That structure completer rewrites the Play data set and you won't be able to tell if there was a problem with the source version of "Play".

3) Splitting datasets apart on the basis of a variable like your "feature" is often inefficient and makes it difficult to do some things like verify the tmin is actually less than or equal to the tmax, or calculate the daily range of temperature (guessing from the data set name "weather" and tmin, tmax variable names). If you made the dates a bit early you could sort on the date and use the Feature variable to rename the value as an ID variable in proc transpose. Allowing you to create a data set like

Year Month Date Tmin Tmax

(and if there are other measures in there like humidity, barometric pressure or similar then the other measures as well).

4) creating dates early is often a good idea as you can do lots of things with formats and or the functions like INTNX and INTCK.

5) include displayed output such as Proc Print, Proc Freq or similar only for things that you actually need. If you are doing these to verify that your "data looks good" that should be done prior to actual reporting. Which might indicate that your "macro" should be in separate parts, not an uncommon coding practice.

 

I might suggest posting an example of the text file you are reading so we can get a better idea of what you have. Copy 5 to 10 lines from the source and paste into a code box opened on the forum with the </> icon to preserve the text layout.

Reeza
Super User


Tutorial on converting a working program to a macro
This method is pretty robust and helps prevent errors and makes it much easier to debug your code. Obviously biased, because I wrote it 🙂 https://github.com/statgeek/SAS-Tutorials/blob/master/Turning%20a%20program%20into%20a%20macro.md

Another option is to combine all your datasets to one and process them at once with another variable in your BY statement if that would make any sense. It depends on what the ultimate goals are. The tutorial above will show you how to generalize a program though.

 


@hayely_bristine wrote:

Hey everyone!  I am new to macros, so bare with me please!  I have some program that produces some tables and plots for a certain dataset.  What I am trying to do is use a macro, so that I can enter a different dataset (same columns, just a different year) and then get the tables and plots for that dataset.  

 

For example, I have 7 data sets in my folder and what I would like to do is somehow rename each dataset Cars1, Cars2,...Cars7, and then I want to use a macro so I can type in "Cars4" into my code once, and then the tables and plots will be generated for the Cars4 data set.

 

Can anyone provide me with an example on how to do this?  Thanks!

 

%let weatherData = \\Client\C$\Math450\USC00010063.DLY;
DATA WEATHER;
  INFILE "&weatherData";
  INPUT Id  $  1-11 
        Year 12-15 
        Month 16-17 
        FEATURE $ 18-21 @22 (D1-D31)(5. +3);
RUN;

DATA TMIN TMAX;
  SET WEATHER;
  IF FEATURE ='TMIN' THEN OUTPUT TMIN;
  ELSE IF FEATURE ='TMAX' THEN OUTPUT TMAX;
  RUN;

  PROC FREQ DATA=TMAX;
  TABLES YEAR*Month/NOCOL NOROW NOPERCENT;
  RUN;

  PROC TRANSPOSE DATA=TMAX(DROP=id) OUT=LONG;
  BY Year Month;
  VAR D1-D31;
  RUN;

  PROC PRINT DATA=LONG;
  RUN;

  PROC SORT DATA=LONG;
  BY Year Month;
  RUN;

  DATA play;
  SET LONG;
  BY Year Month;
  IF first.Month THEN day=0;
  day+1;
  IF Month IN (4,6,9,11) & day=31 THEN DELETE;
  IF Month=2 & day>29 THEN DELETE;
  IF Month=2 & mod(Year,4)~=0 & day=29 THEN DELETE;
  RUN;

DATA play;
  SET play;
  tdate=MDY(Month,day,Year);
  FORMAT tdate mmddyy10.;
  RENAME COL1=TMAX;
  DROP _NAME_;
  RUN;

  DATA PLAY1;
  SET PLAY;
  TMAX1=.;
  IF (COL1 = -9999) THEN TMAX1 =.;
  RUN;

  PROC PRINT DATA=PLAY1;
  VAR Year Month Day Tdate TMAX1;
  RUN; 

  PROC SGPLOT DATA = PLAY;
  by Year;
  scatter x = month y = TMAX;
  RUN;

 

SAS Innovate 2025: Call for Content

Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!

Submit your idea!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 764 views
  • 0 likes
  • 3 in conversation