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

Hello everyone, 

 

recently i wanna to draw a lattice layout plot where lots of sub-plots (cells) are avaliable. such as code like that..:

 

proc template;
	define statgraph myren_density;
		begingraph;
		entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
			"Table 1: Distributions of metals log-transformed concentraions";
		entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
			weight=normal color=CX8470FF) "Note: made by Myren";
		layout lattice / columns=1;
/*Hg*/ cell; cellheader; layout gridded; entry "Hg"; endlayout; endcellheader; layout overlay; histogram eval(log(Hg)); densityplot eval(log(Hg)); endlayout; endcell;

/*Here I want to add several similar cell blocks like cell "Hg" where only variable "Hg" will be changed by other variable name ("Cd"”As“ for example)*/
sidebar / align=bottom; entry "Log-transformed Concentration(μg/g)" / textattrs=(family="Times New Roman" size=12 weight=normal) pad=(left=30); endsidebar; endlayout; endgraph; end; run; proc sgrender data=df template=myren_density; run;

 

I tried to use CALL EXECUTE but failed. It seemed that the CALL EXECUTE routines resolved the codes inside them seperately when SAS finished compiling?

But i hoped  that the produced codes can "be generated together" and "run simultaneously". Obviously  the code below can't. 

Anyone suggestions or better solutions🤔

 

DATA  VARLIST;/*Var list*/
    INPUT  VAR $8.;
DATALINES;
Hg
Cd
Cr
As
Pb
...
;
RUN;

%MACRO CELLS(VAR);/*macro that generating cells*/
cell; cellheader; layout gridded; entry "Hg"; endlayout; endcellheader; layout overlay; histogram eval(log(&VAR.)); densityplot eval(log(&VAR.)); endlayout; endcell;
%MEND CELLS;

DATA _NULL_;
  SET VARLIST;

  IF _N_=1 THEN CALL EXECUTE('%NRSTR(proc template; define statgraph myren_density; begingraph; entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) "Table 1: Distributions of metals log-transformed concentraions"; entryfootnote halign=left textattrs=(size=9 family="Times New Roman" weight=normal color=CX8470FF) "Note: made by Myren"; layout lattice / columns=1;)');/*Beiginning part of proc templete*/

  CALL EXECUTE('%NRSTR(%CELLS('||VAR||'))');/*Generate multiple cells*/

  IF LAST. THEN CALL EXECUTE('%NRSTR(sidebar / align=bottom; entry "Log-transformed Concentration(μg/g)" / textattrs=(family="Times New Roman" size=12 weight=normal) pad=(left=30); endsidebar; endlayout; endgraph; end; run; proc sgrender data=df template=myren_density; run;)');/*End part of proc templete as well as proc sgrender*/

RUN;/*DATA SETP END*/

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
Patrick
Opal | Level 21

Storing the cell names in a macro variable and then looping over it should do the trick.

data varlist;
  input  var $8.;
  datalines;
hg
cd
cr
as
pb
;

%let varlist=;
proc sql noprint;
  select var into :varlist separated by ' ' 
  from varlist
  ;
quit;

%macro cells(var);
  %do i=1 %to %sysfunc(countw(&var));
    %let thisVar=%scan(&var.,&i);
    cell;
      cellheader;
        layout gridded;
        entry "&thisVar";
        endlayout;
      endcellheader;
      layout overlay;
      histogram eval(log(&thisVar));
      densityplot eval(log(&thisVar));
      endlayout;
    endcell;
  %end;
%mend cells;

proc template;
  define statgraph myren_density;
    begingraph;
    entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
      "Table 1: Distributions of metals log-transformed concentraions";
    entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
      weight=normal color=CX8470FF) "Note: made by Myren";
    layout lattice / columns=1;
    %cells(&varlist)
    sidebar / align=bottom;
    entry "Log-transformed Concentration(µg/g)" / textattrs=(family="Times New Roman" 
      size=12 weight=normal) pad=(left=30);
    endsidebar;
    endlayout;
    endgraph;
  end;
run;

 

View solution in original post

7 REPLIES 7
ChrisNZ
Tourmaline | Level 20

Something like this?

%macro cell(var);
		cell;
		  cellheader;
		    layout gridded;
		    entry "&var";
		    endlayout;
		  endcellheader;
		  layout overlay;
		    histogram eval(log(&var));
		    densityplot eval(log(&var));
		   endlayout;
		endcell;
%mend;

proc template;
	define statgraph myren_density;
		begingraph;
		entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
			"Table 1: Distributions of metals log-transformed concentraions";
		entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
			weight=normal color=CX8470FF) "Note: made by Myren";
		layout lattice / columns=1;
 %cell(Hg)
 %cell(Cd)
		sidebar / align=bottom;
		entry "Log-transformed Concentration(μg/g)" / textattrs=(family="Times New Roman" 
			size=12 weight=normal) pad=(left=30);
		endsidebar;
		endlayout;
		endgraph;
	end;
run;

 

 

 

 

myrenO3
Fluorite | Level 6

Yeah, thanks for your reminding. it does really work. But if we have lots of cells to be generated (fifty for example?), perhaps the code would be  a little complex?

Patrick
Opal | Level 21

Storing the cell names in a macro variable and then looping over it should do the trick.

data varlist;
  input  var $8.;
  datalines;
hg
cd
cr
as
pb
;

%let varlist=;
proc sql noprint;
  select var into :varlist separated by ' ' 
  from varlist
  ;
quit;

%macro cells(var);
  %do i=1 %to %sysfunc(countw(&var));
    %let thisVar=%scan(&var.,&i);
    cell;
      cellheader;
        layout gridded;
        entry "&thisVar";
        endlayout;
      endcellheader;
      layout overlay;
      histogram eval(log(&thisVar));
      densityplot eval(log(&thisVar));
      endlayout;
    endcell;
  %end;
%mend cells;

proc template;
  define statgraph myren_density;
    begingraph;
    entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
      "Table 1: Distributions of metals log-transformed concentraions";
    entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
      weight=normal color=CX8470FF) "Note: made by Myren";
    layout lattice / columns=1;
    %cells(&varlist)
    sidebar / align=bottom;
    entry "Log-transformed Concentration(µg/g)" / textattrs=(family="Times New Roman" 
      size=12 weight=normal) pad=(left=30);
    endsidebar;
    endlayout;
    endgraph;
  end;
run;

 

myrenO3
Fluorite | Level 6
Great! The code solves my problems totally!
Thanks for your perfect solution!
Like!
Patrick
Opal | Level 21

And if you don't have a lot of variable names then you can of course pass in the names also directly as a blank list in a single or multiple calls to the macro.

proc template;
  define statgraph myren_density;
    begingraph;
    entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
      "Table 1: Distributions of metals log-transformed concentraions";
    entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
      weight=normal color=CX8470FF) "Note: made by Myren";
    layout lattice / columns=1;
    %cells(hg cd cr as)
    %cells(pb)
    sidebar / align=bottom;
    entry "Log-transformed Concentration(µg/g)" / textattrs=(family="Times New Roman" 
      size=12 weight=normal) pad=(left=30);
    endsidebar;
    endlayout;
    endgraph;
  end;
run;
Tom
Super User Tom
Super User

It should be possible with CALL EXECUTE. Are you sure the code you are generating will work? Did you try an example first to make sure? If it CAN work then just check the log to see if the lines of code your data step generated match what you want. They are easy to see in the log since they will have + at the start of the line.

It is probably going to be easier debug the code generation if you use the data step just write the series of macro calls to a temporary text file (use PUT statement). Then to run it you just have the beginning and ending statements of the PROC TEMPLATE code in your program and use %INCLUDE to call in the macro calls from the temporary file at the place where you need them.

 

No need for macro or macro variables.

filename code temp;
data _null_;
  set varlist ;
  file code ;
  put 'cell;'
    / '  cellheader;'
    / '    layout gridded;'
    / '      entry ' var :$quote. ';'
    / '    endlayout;'
    / '  endcellheader;'
    / '  layout overlay;'
    / '    histogram eval(log(' var '));'
    / '    densityplot eval(log(' var '));'
    / '  endlayout;'
    / 'endcell;'
  ;
run;

proc template;
  define statgraph myren_density;
    begingraph;
    entrytitle textattrs=(size=12 family="Times New Roman" weight=bold) 
      "Table 1: Distributions of metals log-transformed concentraions";
    entryfootnote halign=left textattrs=(size=9 family="Times New Roman" 
      weight=normal color=CX8470FF) "Note: made by Myren";
    layout lattice / columns=1;
 %include code / source2;
    sidebar / align=bottom;
    entry "Log-transformed Concentration(µg/g)" / textattrs=(family="Times New Roman" 
      size=12 weight=normal) pad=(left=30);
    endsidebar;
    endlayout;
    endgraph;
  end;
run;
myrenO3
Fluorite | Level 6
Thanks for your suggestion! Good idea
Putting the macro calls to a temporary file and using %INCLUDE haalso sound cool. I' ll have a try later.

sas-innovate-2024.png

Don't miss out on SAS Innovate - Register now for the FREE Livestream!

Can't make it to Vegas? No problem! Watch our general sessions LIVE or on-demand starting April 17th. Hear from SAS execs, best-selling author Adam Grant, Hot Ones host Sean Evans, top tech journalist Kara Swisher, AI expert Cassie Kozyrkov, and the mind-blowing dance crew iLuminate! Plus, get access to over 20 breakout sessions.

 

Register now!

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
  • 7 replies
  • 491 views
  • 1 like
  • 4 in conversation