bcg
bcg

Reputation: 17

how to generate unique random vector on each iteration?

I'm new to SAS, I would like to produce plot for each random numerical vector. therefore I have wrapped my proc iml with a macro, and have tried to invoke it before calling the macro generate_scatter_plot. but I get the same set of points each iteration.

Can somebody please explain what is the proper way to do it SAS.

  %MACRO generate_random_points();
proc iml;
    N = 6;
    rands = j(N,1);
    call randgen(rands, 'Uniform');  /* SAS/IML 12.1 */

    submit rands;
        data my_data;
            input x y @@;
            datalines;
            &rands
            ;
        run;
    endsubmit;
%MEND;

%MACRO generate_scatter_plot();
/* call execute('%generate_random_points();'); */
proc sgplot data=my_data;
scatter x=x y=y;
run;
%MEND;

data _null_;
do i = 1 to 20;
call execute('%generate_scatter_plot();');
end;
run;

I find SAS different from the rest of languages out there.

Thank you in advance to all who are willing to help!

Upvotes: 0

Views: 221

Answers (3)

Stu Sztukowski
Stu Sztukowski

Reputation: 12909

Although you are using IML to pass data as text into a datalines statement, you really do not need to do this. There are simpler ways of achieving your goal.

SAS does everything through datasets. They're analogous to Data Frames in Pandas. If you want to create a random vector of data, you'll create it within a dataset and use that within other procedures. datalines should be avoided in production whenever possible. There are some very special cases where it is useful, but it's mainly used for sample data or prototyping.

SAS will randomly generate data based on the system clock unless you set a seed through call streaminit(). You should always get new points. A much simpler way to achieve your results is shown below. The below macro will generate a new random dataset and plot it each time you call it.

%macro generate_scatter_plot(n=100);
    data random;
        do i = 1 to &n;
            x = rand('uniform');
            y = rand('uniform');
            output;
        end;

        drop i;
    run;

    proc sgplot data=random;
        scatter x=x y=y;
    run;
%mend;

%generate_scatter_plot(n=100);
%generate_scatter_plot(n=1000);

Upvotes: 0

Tom
Tom

Reputation: 51591

If you are working in IML you should not have any need to use the SAS macro language to generate code.

You already showed how you can generate the random numbers into a IML matrix.

And you can use the SUBMIT/ENDSUBMIT block to call your PROC SGPLOT code.

What you seem to be missing is the IML syntax for converting a matrix into a dataset. https://blogs.sas.com/content/iml/2011/04/18/writing-data-from-a-matrix-to-a-sas-data-set.html

proc iml;
N = 6;
x = t(1:N);
y = j(N,1);
call randgen(y, 'Uniform');

create my_data var {x y};
append;  
close my_data; 

submit;
proc sgplot data=my_data;
scatter x=x y=y;
run;
endsubmit;

quit;

Upvotes: 0

Reeza
Reeza

Reputation: 21274

  • IML is not needed, a data step loop can generate the random values
  • Assuming you're looking at learning macro programming
  • CALL EXECUTE is required in a data step but not outside the data step
  • CALL EXECUTE can also generate code similar to macro
  • MPRINT/MLOGIC options help when debugging macro code otherwise code is not displayed to log

The following expands a bit on your logic to demonstrate the functionality of macro's.

options mprint mlogic;


%macro generate_random_points(Num=);
*Macro to generate random numbers;
*number of points generated are equal to the NUM=parameter;
data my_data;
do i=1 to &num.;
x=rand('uniform');
y=rand('uniform');
output;
end;
run;

%mend;




%macro generate_scatter_plot(Num_Points=);

*create random data with specified points;
%generate_random_points(Num=&Num_Points);

*graph data;
proc sgplot data=my_data;
scatter x=x y=y;
run;

%MEND;


*Run macro with different parameters in loop;
data _null_;
do i = 3 to 5;
         call execute(catt('%generate_scatter_plot(Num_Points=', i, ');'));
end;
run;

option nomprint nomlogic;

And a slight variation on your process:

data _null_;
do i = 3 to 5;
         call execute(catt("Title 'Num Points = ", i, " '; ", ' %generate_scatter_plot(Num_Points=', i, ');'));
end;
run;

Upvotes: 0

Related Questions