Reputation: 57
Does anybody know how to find the non-zero minimum in a row using the min function in SAS? Or any other option in SAS code?
Current code:
PIP_factor = `min(PIPAllAutos, PIPNotCovByWC, PIPCovByWC, PIPNotPrincOpByEmpls);
Upvotes: 2
Views: 5563
Reputation: 545
/* For each row, find the variable name corresponding to the minimum value */
proc iml;
use DATASET; /* DATASET is your dataset name of interest */
read all var _NUM_ into X[colname=VarNames]; /* read in only numerical columns */
close DATASET;
idxMin = X[, >:<]; /* find columns for min of each row */
varMin = varNames[idxMin]; /* corresponding var names */
print idxMin varMin;
For Max:
idxMax = X[, <:>];
I wasn't familiar with the operator above, SAS provides a helpful table for IML operators:
In PROC IML
you can also create new datasets/append the results to your old one if you need them later on.
Full blog post: source, all credit goes to Rick Wicklin at SAS
edit: For the non-zero part, I would just do a PROC SQL
using a WHERE variable is not 0
to filter before feeding it in the PROC IML
. I am sure it can be done within PROC IML
, but I just started using it myself. So, please comment if you know a way around it in PROC IML
and I will include the fix.
Upvotes: 0
Reputation: 124
This one doesn't suffer from 9999 limitation of the approved answer.
%macro minnonzero/parmbuff;
%local _argn _args _arg;
/* get rid of external parenthesis */
%let _args=%substr(%bquote(&syspbuff),2,%length(%bquote(&syspbuff))-2);
%let _argn=1;
min(
%do %while (%length(%scan(%bquote(&_args),&_argn,%str(|))) ne 0);
%let _arg=%scan(%bquote(&_args),&_argn,%str(|));
%if &_argn>1 %then %do;
,
%end;
ifn(&_arg=0,.,&_arg)
%let _argn=%eval(&_argn+1);
%end;
);
%mend;
You call it with pipe-separated list of arguments, e.g.
data piesek;
a=3;
b="kotek";
c=%minnonzero(a|findc(b,"z");
put c; /* 3, "kotek" has no "z" in it, so findc returns 0 */
run;
Upvotes: 0
Reputation: 9618
Here is another way, using the IFN function:
data null_;
PIPAllAutos = 2;
PIPNotCovByWC = .;
PIPCovByWC = 0;
PIPNotPrincOpByEmpls = 1;
PIP_factor = min(ifn(PIPAllAutos=0, . ,PIPAllAutos)
, ifn(PIPNotCovByWC=0, . ,PIPNotCovByWC)
, ifn(PIPCovByWC=0, . ,PIPCovByWC)
, ifn(PIPNotPrincOpByEmpls=0, . ,PIPNotPrincOpByEmpls)
);
put PIP_factor=;
run;
Note the min
function ignores missing values; the ifn
function sets zero values to missing.
Might be more typing than it's worth; offered only as an alternative. There are many ways to skin the cat.
Upvotes: 1
Reputation: 63424
I think you need to use an array solution, ie
array pipArray pip:; *or whatever;
PIP_factor=9999;
do _n = 1 to dim(pipArray);
if pipArray[_n] > 0 then
PIP_factor = min(PIP_factor,pipArray[_n]);
end;
Or somesuch.
Upvotes: 2