I registered a file inside a SAS Code Node on SAS Miner
%em_register(key=plotdata, type=DATA);
and then used it normally inside that node.
Afterwards, I wanted to access that registered file inside another SAS Code Node but I'm not being able to.
How can I achieve this?
Thanks.
Hi @martasls,
Thanks for your question! I wanted to let you know that a SAS expert is looking into this and will get back to you soon.
Best,
Anna
Macro variables do not persist across nodes in SAS Enterprise Miner (EM). Thus, the macro variable EM_USER_PLOTDATA will not be defined outside of the SAS Code node that created it. If you make an identical call to EM_REGISTER in a successor SAS Code node, a new value will be supplied to the macro variable, and it will be independent of the macro variable created in the predecessor node. EM has its own system of keeping track of things, which is not documented, but can be inferred. I am guessing a new symbol table is created for each SAS Code node, with some values populated by reading SAS tables created by predecessor nodes. If this is all mysterious to you, fear not, there is a kludge to extract some information from predecessor nodes.
Consider program number 1 which creates a SAS table and a SAS program using %EM_REGISTER.
/*
Object 1: SAS Data Set
Object 2: SAS program file
*/
%EM_REGISTER(KEY=FREQ,TYPE=DATA);
%EM_REPORT(KEY=FREQ,VIEWTYPE=DATA,AUTODISPLAY=Y);
proc freq data=&EM_IMPORT_DATA;
tables %scan(%EM_NOMINAL_INPUT,1,%str( )) / out=&EM_USER_FREQ;
run;
%EM_REGISTER(KEY=HELLO,TYPE=FILE,EXTENSION=SAS);
data _null_;
file "&EM_USER_HELLO";
put "data _null_;";
put ' put "Hello World!";';
put "run;";
run;
If you run this program, and if you have an imported training or raw data set with at least one nominal input variable, you will get a frequency table for the first nominal input. The macro variable EM_USER_FREQ will contain the name of the table. You could write this name out to a hardcoded location that you can reference later, but the value may reference a SAS library that does not exist in the successor node. Note that you also get a SAS program with the classic "Hello, World!" program.
If you attach a successor node anywhere downstream from the original SAS code node, the following program will find the SAS data set and the SAS program created by the most recent SAS Code node in the process flow sequence leading to the current SAS Code node.
/*---- RegisteredData_Prog2.sas ----*/
/*---- First, a few macros ----*/
/*---- Macro to find path to current SAS Code node ----*/
/*---- Limits: Assumes sequential path to this node ----*/
%macro FindDiagPath(DSName=,OutDS=,TerminalNode=);
proc sql noprint;
select FROM into :LastNode
from &DSName
where lowcase(TO)=lowcase("&TerminalNode");
quit;
%let DiagramPath=&LastNode;
%do %while( (%substr(&LastNode,1,3) ne Ids) & (&LastNode ne));
proc sql noprint;
select FROM into :LastNode2
from &DSName
where lowcase(TO)=lowcase(strip("&LastNode"));
quit;
%let LastNode=&LastNode2;
%let DiagramPath=%cmpres(&DiagramPath &LastNode);
%end;
%put &DiagramPath;
data &OutDS;
attrib DiagramPath length=$32767
Order ReverseOrder length=8
EMnode length=$32
;
keep Order ReverseOrder EMnode;
DiagramPath="&DiagramPath";
NumWord=countw(DiagramPath);
do ReverseOrder=1 to NumWord;
Order=NumWord-ReverseOrder+1;
EMnode=scan(DiagramPath,ReverseOrder,' ');
output;
end;
run;
/*---- You can sort in order if desired ----*\
proc sort data=&OutDS;
by Order;
run;
\*----*/
%mend FindDiagPath;
/*---- Store the contents of a folder in a SAS table ----*/
%macro WriteDirDS(FolderName,DSName);
filename inpfile pipe "dir ""&FolderName"" /b /d" console=min;
data &DSName;
attrib LINE length=$512
FILENAME length=$512;
infile inpfile;
input;
LINE=_infile_;
FILENAME=strip(LINE);
output;
keep FILENAME;
run;
filename inpfile clear;
%mend WriteDirDS;
/*---- Extract values of macro variable from previous SAS Code node ----*/
%macro EM_REGISTER_LAST(KEY=,TYPE=,LastCodeNode=);
%local DSName;
%if ("&LastCodeNode" ne "Not Found") %then %do;
/*---- Step 3: Find DATA or FILE object ----*/
%if (%upcase(&TYPE) eq DATA) %then %do;
%let DSName=&LastCodeNode._&KEY;
ods output members=&EM_USER_Dsets;
proc datasets library=&EM_LIB;
quit;
ods output close;
proc print data=&EM_USER_Dsets;
run;
data &EM_USER_Dsets;
set &EM_User_Dsets end=lastobs;
if (upcase(strip(Name))=upcase(strip("&DSName"))) then do;
output;
stop;
end;
if (lastobs) then do;
Name="Not Found";
output;
end;
run;
%end;
%else %if (%upcase(&TYPE) eq FILE) %then %do;
%let EMLIBPATH=%sysfunc(pathname(&EM_LIB));
%put &EMLIBPATH;
%WriteDirDS(&EMLIBPATH\&LastCodeNode,&EM_USER_Sprogs);
proc print data=&EM_USER_Sprogs;
run;
data &EM_USER_Sprogs;
set &EM_USER_Sprogs end=lastobs;
if (strip(upcase(FILENAME))=strip(upcase("&KEY..SAS"))) then do;
output;
stop;
end;
if (lastobs) then do;
FILENAME="Not Found";
output;
end;
run;
%end;
%end;
%else %do;
%put ERROR: Only DATA or FILE types are allowed.;
%end;
%mend EM_REGISTER_LAST;
/*---- Declare Stuff ----*/
%global LastCode DGraphData ThisNode;
%let DGraphData=%sysfunc(strip(&EM_LIB)).Em_dgraph;
%let ThisNode=%cmpres(&EM_NODEID);
/*---- Step 1: Find predecessor nodes ----*/
/*---- SAS Table to hold process flow node information ----*/
%EM_REGISTER(KEY=Path,TYPE=DATA);
%EM_REPORT(KEY=Path,VIEWTYPE=DATA,AUTODISPLAY=Y,DESCRIPTION=%str(Diagram Path));
%FindDiagPath(DSName=&DGraphData,OutDS=&EM_USER_Path,TerminalNode=&ThisNode);
/*---- Step 2: Find last code node ----*/
data _null_;
set &EM_USER_Path end=lastobs;
if (substr(EMnode,1,6)="EMCODE") then do;
call symputx("LastCode",EMnode);
stop;
end;
if (lastobs) then do;
call symputx("LastCode","Not Found");
end;
run;
/*---- Predecessor SAS files ----*/
%EM_REGISTER(KEY=Sprogs,TYPE=DATA);
%EM_REPORT(KEY=Sprogs,VIEWTYPE=DATA,AUTODISPLAY=Y,DESCRIPTION=%str(Matching SAS Programs));
%EM_REGISTER_LAST(KEY=Hello,TYPE=File,LastCodeNode=&LastCode);
/*---- Predecessor SAS tables ----*/
%EM_REGISTER(KEY=Dsets,TYPE=DATA);
%EM_REPORT(KEY=Dsets,VIEWTYPE=DATA,AUTODISPLAY=Y,DESCRIPTION=%str(Matching Data Sets));
%EM_REGISTER_LAST(KEY=freq,TYPE=data,LastCodeNode=&LastCode);
The information you desire is stored in two separate SAS tables displayed using %EM_REPORT. You should be able to use that information to do just about anything you want with the SAS table and the SAS program. For the program to work, I had to know the two values of KEY, namely FREQ and HELLO.
The success of the above program depends on SAS Enterprise Miner maintaining the current naming conventions for objects created by %EM_REGISTER. Consequently, it may have an expiration date.
While this is obviously a kludge, I am hoping that you find it to be useful.
Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!
Use this tutorial as a handy guide to weigh the pros and cons of these commonly used machine learning algorithms.
Find more tutorials on the SAS Users YouTube channel.