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

I want to parse the arguments to a SAS/IML module independently of using the predefined "name=value" schema, which limits me to defining all of the name/value pairs that I may want to use. For example,

start example( control_parameter, var1=value1, var2=value2, ..., varN=valueN ) ;

/* parse the argument list and process the parameters according to the control_parameter,
* which defines the operations to perform on the argument variables var1, ..., varN
*/
finish ;

This would give me a capability similar to MATLAB's nargin variable and SAS/MACRO's &SYSPARM representation of an argument vector. Is there a SAS/IML function that I can use to parse the argument string?

 

Also, is there a SAS/IML equivalent of the base SAS SELECT construct, or must I use repeated IF-THEN-ELSE statements?

1 ACCEPTED SOLUTION

Accepted Solutions
Rick_SAS
SAS Super FREQ

I would pass in a named list. You can query to list to find out how many items it has. You can use the LISTGETALLNAMES function to get the keywords that are passed in. You can then use the ListGetItem function to get the values for the keywords that are present in the list.

 

Regarding SELECT-WHEN: That syntax is used for SCALAR values in the DATA step. In IML, use the LOC function to identify values and then process those elements however you want. For example, the following programs compare the SELECT-WHEN statement in the DATA step to using the LOC function in IML:

/* example of using the SELECT statement */
data Heart1;
set sashelp.heart;
select (Smoking_Status);
   when ('Non-smoker')        Smoking_Cat=1;
   when ('Light (1-5)')       Smoking_Cat=2;
   when ('Moderate (6-15)')   Smoking_Cat=3;
   when ('Heavy (16-25)')     Smoking_Cat=4;
   when ('Very Heavy (> 25)') Smoking_Cat=5;
   otherwise                  Smoking_Cat=.;
end;
run;


proc iml;
use sashelp.heart;
read all var "Smoking_Status";
close;

case={'Non-smoker' 'Light (1-5)' 'Moderate (6-15)' 'Heavy (16-25)' 'Very Heavy (> 25)'};
result = {1 2 3 4 5};

Smoking_Cat = j(nrow(Smoking_Status), 1, .);
do i = 1 to ncol(case);
   idx = loc(Smoking_Status=case[i]);
   if ncol(idx)>0 then 
      Smoking_Cat[idx]=result[i];
end;

View solution in original post

6 REPLIES 6
Rick_SAS
SAS Super FREQ

Is your example what you WANT or what you DON'T want? Please post an example of what you WANT, along with examples of calling the function and what you expect the function to do for each call.

rbettinger
Pyrite | Level 9

I want to parse the arguments to a SAS/IML module independently of using the predefined "name=value" schema, which limits me to defining all of the name/value pairs that I may want to use. For example,

 

start example( var1=value1, var2=value2, ..., varN=valueN ) ;

/* Let us assume that there is a SAS/IML function called "getopt" (like the C language getopt() function) that will return a name/value pair */
/* then we could write code like this: */

do while( 1 ) ;
variableNameValuePair = getopt() ;
if isEmpty( variableNameValuePair ) then leave ;
varName = scan( variableNameValuePair, 1 ) ; varValue = scan( variableNameValuePair, 2 ) ;
/* perform further processing based on contents of varName, e.g., store varValue in list item L$varname */
end ;

finish ;

This would give me a capability similar to MATLAB's nargin variable and SAS/MACRO's &SYSPARM representation of an argument vector. Is there a SAS/IML function that I can use to parse the argument string?

 

Also, is there a SAS/IML equivalent of the base SAS SELECT construct, or must I use repeated IF-THEN-ELSE statements?

Rick_SAS
SAS Super FREQ

I would pass in a named list. You can query to list to find out how many items it has. You can use the LISTGETALLNAMES function to get the keywords that are passed in. You can then use the ListGetItem function to get the values for the keywords that are present in the list.

 

Regarding SELECT-WHEN: That syntax is used for SCALAR values in the DATA step. In IML, use the LOC function to identify values and then process those elements however you want. For example, the following programs compare the SELECT-WHEN statement in the DATA step to using the LOC function in IML:

/* example of using the SELECT statement */
data Heart1;
set sashelp.heart;
select (Smoking_Status);
   when ('Non-smoker')        Smoking_Cat=1;
   when ('Light (1-5)')       Smoking_Cat=2;
   when ('Moderate (6-15)')   Smoking_Cat=3;
   when ('Heavy (16-25)')     Smoking_Cat=4;
   when ('Very Heavy (> 25)') Smoking_Cat=5;
   otherwise                  Smoking_Cat=.;
end;
run;


proc iml;
use sashelp.heart;
read all var "Smoking_Status";
close;

case={'Non-smoker' 'Light (1-5)' 'Moderate (6-15)' 'Heavy (16-25)' 'Very Heavy (> 25)'};
result = {1 2 3 4 5};

Smoking_Cat = j(nrow(Smoking_Status), 1, .);
do i = 1 to ncol(case);
   idx = loc(Smoking_Status=case[i]);
   if ncol(idx)>0 then 
      Smoking_Cat[idx]=result[i];
end;
rbettinger
Pyrite | Level 9

Both answers are very nice solutions to my questions. Thank you so much!

Ksharp
Super User

Also could try PROC FORMAT.

 

proc format;
invalue fmt
   'Non-smoker'       =1
   'Light (1-5)'       =2
   'Moderate (6-15)'   =3
   'Heavy (16-25)'    =4
   'Very Heavy (> 25)' =5
;
run;


proc iml;
use sashelp.heart(obs=100);
read all var "Smoking_Status";
close;  
Smoking_Cat=j(nrow(Smoking_Status),1,.);
Smoking_Cat=inputn(Smoking_Status,'fmt.');

print Smoking_Status Smoking_Cat ;
quit;
rbettinger
Pyrite | Level 9
Very interesting idea. Thank you for your insight.

sas-innovate-white.png

🚨 Early Bird Rate Extended!

Join us for SAS Innovate 2025, our biggest and most exciting global event of the year, in Orlando, FL, from May 6-9.

 

Lock in the best rate now before the price increases on April 1.

Register now!

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 6 replies
  • 1313 views
  • 0 likes
  • 3 in conversation