By Eli Kling using

*sas*V9.2/BaseFrom time to time the developers in Cary make an addition that excites even sas–dinosaurs like myself. Not everyone sees the potential of, or even the need for proc FCMP. However, I think it signals a major change in the way sas is used and developed and opens the door for cutting edge statistical modelling also on platforms that have ‘only’ Base/Stat/Graph.

The obvious challenge I first tackled as a learning exercise was calculating the Benjamini-Hochberg FDR correction to a vector of p-values. It was the focus of my dissertation a thousand years ago. I will discuss it in a following entry.

Good practice calls to first check that the vector passed in is appropriate and abort the processing otherwise. The BKf_GateKeepr function below checks that all the elements of a vector contain values between 0 and 1 and returns 0 for OK and 1 for Failed. If the check failed it also puts a message in the log.

As I intend to expand the functionality of this function I included a ‘Check’ switch indicating what check to perform. In the version below only ‘PVALUE’ is programmed.

You will also notice that the sas editor has a problem to correctly colour the key words. I am sure that will be fixed in later versions.

**proc**

**delete**data=sasuser.BusinessKenLibrary;

**run**;

options cmplib=sasuser.BusinessKenLibrary;

**proc**

**fcmp**outlib=sasuser.BusinessKenLibrary.dev;

/* RC=BKf_GateKeeper(Vector,Check)

a utility to be used to check vector inputs

Input Vector - the vector of values to check

Check - what to check

pvalue: verify all values between 0 and 1

output RC - 0 = passed check

1 = failed check

*/

function BKf_GateKeeper(vector(*),Check$);

put "check" Check;

N=dim(Vector);

RC=

**0**; if Upcase(Check)="PVALUE" then do;

do i=

**1**to N; if not(

**0**<=vector[i]<=**1**) then RC=**1**; end;

if RC=

**1**then put "<< BK Values Gate Keeper: A vector of pvalues was expected but at least one value was not in the interval [0,1]. Note, it might have been a missing value. >>"; end;

return(RC);

endsub;

**run**;

/********/

/* Test */

/********/

**data**test;

* Array parameters to subroutine calls must be temporary arrays;

array a(3) _temporary_;

a[

**1**]=**5**; a[

**2**]=**0.01**; a[

**3**]=**0.96**; RC=BKf_GateKeeper(a,"Pvalue");

**run**;

**proc**

**run**;

/*****************************************************************/

/* Code End */

/*****************************************************************/