Here's a quick tip to keep in mind when you write SAS/IML programs: although the SAS/IML documentation lists about 300 functions that are built into the SAS/IML language, you can also call hundreds of functions in Base SAS. Furthermore, you can pass in SAS/IML vectors for arguments to the functions. This article shows that you can also pass in multiple vectors, provided that they are all the same dimensions.
I recently blogged about the four essential functions for statistical programmers: the PDF (probability density function), CDF (cumulative distribution function), QUANTILE, and RAND (or RANDGEN) functions. The first three of these functions are Base SAS functions, but you can call them from SAS/IML programs and you can send in vectors as arguments, as shown in the following statements:
proc iml; x = do(-3, 3, 0.5); /* 13 points: -3, -2.5, ..., 2.5, 3 */ /* call Base SAS function with one vector */ f = pdf("Normal", x);/* 13 points out: f(-3), f(-2.5), ..., f(3) */ |
The f vector contains the density of the standard normal distribution at 13 locations. I sent 13 points into the function, I got 13 points out.
The PDF function for the normal distribution accepts two optional parameters: a mean and a standard deviation parameter. By default, the mean for the normal family is set to zero. Therefore, the previous PDF call is equivalent to the following call, which explicitly specifies the mean parameter to zero:
f = pdf("Normal", x, 0); /* one vector parameter; one scalar */ |
It is perfectly fine to mix and match parameters in this way. You can specify one vector parameter and one or more scalar parameters. You can also specify two or more vector parameters for the PDF function, provided that they are all the same dimensions (shape). For example, the following statements are valid:
mu = -6:6; /* vector of 13 means */ f = pdf("Normal", x, mu); /* f(x[i]; mu[i]), i=1..13 */ |
This code evaluates the normal PDF function with parameter mu[i] at the point x[i] for i=1..13. The syntax shows that you can pass multiple vectors to a Base SAS function, provided that the vectors are the same shape, in this case a 1x13 vector. However, you usually cannot pass vectors of different shapes into a Base SAS function, as shown in the following statement:
f = pdf("Normal", x, {0 1}); /* mean=0 and 1? Nope, wrong dimensions! */ |
If you execute the previous statement, the following error message appears:
»ERROR: (execution) Matrices do not conform to the operation. |
The message says "Matrices do not conform to the operation," which means that the parameters have different shapes.
In general, when you call Base SAS functions from the SAS/IML language, you can pass in vectors of parameters. The shape of the parameter vector determines the shape of the function's output. You can also mix scalar parameters and vector parameters. However, if you pass in more than one vector (or matrix) as a parameter, each non-scalar parameter must have the same shape.
11 Comments
Hello Rick, I am wondering can PROC IML Do Loop call a standard procedure like PROC MCMC in the loop? Thanks
Yes. See my blog post "Calling SAS Procedures from the SAS/IML Language."
Hello Rick,
Thanks for the helpful blogs... I recently read the post regarding the creating matrix by using do loops and have a question for you. I am very new to proc IML and really want to tackle it with all of your guys advises..By folloing a logic, I am trying to create a matrix and pass my variables that had been read from the data set into the matrix.
this is what I do
proc IML;
USE work.Test1;
READ ALL VAR {Var 1....Var 26} into rm ;
CLOSE work.Test1;
n=NROW(rm);
d=J(n,1,0);
c=d;
c=n[,2:27]-n[,1:26];
x=n|d||c;
free n;
quit;
This is what passed through the log:
ERROR: (execution) Matrix has not been set to a value.
operation : || at line 1006 column 9
operands : d, c
d 0 row 0 col (type ?, size 0)
How can I deal with the problem? I would highly appreciate the specific advise
The best way to get programming advice is to post questions to the SAS/IML Discussion Forum at http://communities.sas.com/community/sas_iml_and_sas_iml_studio
Someone there will help.
There are many mistakes in this program. I can't give specific advise to everyone who writes, but try:
c=d || rm;
c = c[,2:27]-c[,1:26];
x=n||d||c;
free c;
hi ,
the following code generates a column vector of a sample of size 10 from the standard normal density, do i have a code to directly generate a column vector without taking the transpose:
proc iml;
mhat=0;
do e=1 to10;
*generating standard normal random variable;
x=rannor(100);
mhat=mhat//x;
end;
mhat=remove(mhat,1);
mhat=t(mhat);
print mhat;
quit;
To generate a vector of random normal values, use
See p. 28 of my book Statistical Programming in SAS/IML Software. That chapter is available as a FREE download.
Pingback: Generate binary outcomes with varying probability - The DO Loop
Pingback: Break a sentence into words in SAS - The DO Loop
Pingback: How to visualize a kernel density estimate - The DO Loop
I have a problem where I need to generate a vector of values from using the rantbl function where I want to change the probabilities via a vector of probabilities:
A brute force way of doing this with lots of commas would be this:
proc iml;
rt = RANTBL(j(10,1,8957553), 0.2, 0.125, 0.125, 0.125, 0.125, 0.04, 0.04, 0.04, 0.04, 0.04, 0.0055556,
0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556,
0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556, 0.0055556,
0.0055556, 0.0055556, 0.0055556) -1;
print rt;
run;
But I would like to use something where I can change the probabilities with a different vector of probabilities.
Obviously I can write a routine to do this but it would be nice if I could pass the vector of probabilities to rantbl in
code that would look like this:
proc iml ;
prob = (1/5)||j(1,4,(5/40))||j(1,5,(2/50))||j(1,18,(1/180)) ;
rt = RANTBL(j(10,1,8957553), prob) -1;
print rt ;
run;
For discussion and examples, see "Simulate categorical data in SAS":