BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
whymath
Lapis Lazuli | Level 10
I have try to write a user-defined function MinDis() and apply it in data step, this function is used to compute the minimum distance from one point to each element of an (numeric)array. Code fllowing:
proc fcmp outlib = work.funcs.Math;
    function MinDis(Exp,Arr[*]);
        array dis[2] /nosymbols;
        call dynamic_array(dis,dim(Arr));
        do i = 1 to dim(Arr);
            dis[i] = abs((Exp - Arr[i]));
        end;
        return(min(of dis[*]));
    endsub;
quit;

option cmplib=work.funcs ; 

data MinDis;
    input LamdazLower LamdazUpper @;
    cards;
    2.50 10.0
    2.51 10.8
    2.49 9.97
    2.75 9.50
    ;
run;

data _null_;
    set ;

    array _PTN_ [14] _temporary_ (0.5,1,1.5,2,2.5,3,4,5,6,7,8,9,10,12);
    StdLamZLow = MinDis(LamdazLower,_PTN_);
    StdLamZUpp = MinDis(LamdazUpper,_PTN_);
    put _all_;
run;

It was compile rightly but gave wrong results. StdLamZLow just get the minimum distance from LamdazLower to the first two element of array _PTN_.

When I rewrite the dim of dis as 999 or something very big and get rid of call dynamic_array statement I would get it right. But I surely want to know why min(of dis[*]) just take dis as a 2-dim array.

By the way, how can I use implied DO-loops do over ... to instead of explicit DO loops? I have tried several times but haven`t success yet.

Thanks for any hints.

1 ACCEPTED SOLUTION

Accepted Solutions
KachiM
Rhodochrosite | Level 12

@whymath 

 

The issue here is that OF operator for a Dynamically created Array in FCMP which is NOT supported. There are two ways to solve your problem - one using Dynamic array and the other without it. In the former, we compare absolute difference of the previous and the current to choose the minimum. In the second we use MIN function to choose the minimum.

 

Let us see the first solution.

 


proc fcmp outlib = work.funcs.Math;
    function MinDis(Exp,Arr[*]);
        array dis[1] / nosym;
        call dynamic_array(dis,dim(Arr));
        mindis = constant('BIG');
        do i = 1 to dim(Arr);
            dis[i] = abs((Exp - Arr[i]));
            if mindis > dis[i] then mindis = dis[i]; * get minimum distance;
        end;
        return(mindis);
    endsub;
quit;

NOSYM is a short form for NOSYMBOLS. MINDIS is assigned to an impossible big positive value as Minimum Distance. Each absolute difference is compared to previous to get the current minimum. Finally, MINDIS has the final minimum value which is returned to the Data Step. The array DIS[ ] is a waste of memory and hence the second solution.

 

The second solution avoids the use of the array, DIS[ ] but uses the _temporary_ array passed by the Data Step. Here we compare the previous MINDIS with the i-th absolute difference to choose the minimum value.

 

/** No Dynamic_Array **/

proc fcmp outlib = work.funcs.Math;
    function MinDis(Exp,Arr[*]);
        mindis = Constant('BIG');
        do i = 1 to dim(Arr);
            mindis = min(mindis, abs(Exp - Arr[i]));
        end;
        return(mindis);
    endsub;
quit;

Hope this answers your question.

View solution in original post

4 REPLIES 4
PeterClemmensen
Tourmaline | Level 20

A few things:

 

- What is your desired result given _PIN_? Probably makes it easier to help you.

 

- I assume that you misspelled nosymbols as symbols in your Array Statement?

 

- You should always use the Varargs Option when you want the function to accept a variable number of arguments (like an array)

 

- Do Over syntax is for implicit arrays only. PROC FCMP does not support implicit arrays.

whymath
Lapis Lazuli | Level 10

1 The desired result of StdLamZLow should be the minimum distance from LamdazLower to each element of array _PTN_, that is minimum of (abs(LamdazLower-_PTN_[i])), am I more clear now?

2. Yes, I misspelled the option nosymbols. Now it is corrected.

3. I don't realize it is neccessary cause I just get an rig

4. Thank you for the fourth tip.

KachiM
Rhodochrosite | Level 12

@whymath 

 

The issue here is that OF operator for a Dynamically created Array in FCMP which is NOT supported. There are two ways to solve your problem - one using Dynamic array and the other without it. In the former, we compare absolute difference of the previous and the current to choose the minimum. In the second we use MIN function to choose the minimum.

 

Let us see the first solution.

 


proc fcmp outlib = work.funcs.Math;
    function MinDis(Exp,Arr[*]);
        array dis[1] / nosym;
        call dynamic_array(dis,dim(Arr));
        mindis = constant('BIG');
        do i = 1 to dim(Arr);
            dis[i] = abs((Exp - Arr[i]));
            if mindis > dis[i] then mindis = dis[i]; * get minimum distance;
        end;
        return(mindis);
    endsub;
quit;

NOSYM is a short form for NOSYMBOLS. MINDIS is assigned to an impossible big positive value as Minimum Distance. Each absolute difference is compared to previous to get the current minimum. Finally, MINDIS has the final minimum value which is returned to the Data Step. The array DIS[ ] is a waste of memory and hence the second solution.

 

The second solution avoids the use of the array, DIS[ ] but uses the _temporary_ array passed by the Data Step. Here we compare the previous MINDIS with the i-th absolute difference to choose the minimum value.

 

/** No Dynamic_Array **/

proc fcmp outlib = work.funcs.Math;
    function MinDis(Exp,Arr[*]);
        mindis = Constant('BIG');
        do i = 1 to dim(Arr);
            mindis = min(mindis, abs(Exp - Arr[i]));
        end;
        return(mindis);
    endsub;
quit;

Hope this answers your question.

whymath
Lapis Lazuli | Level 10
Very impressive. thanks a lot.

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 4 replies
  • 772 views
  • 1 like
  • 3 in conversation