Statistical programming, matrix languages, and more

SAS IML

Reply
Occasional Contributor
Posts: 19

SAS IML

I am new to SAS and am using proc iml to write some functions. Shoe is an already defined and working function that returns n numbers (in this case 2). I am trying to write a new function that returns a dataset that has the cards as one variable and the amount of the bet stored in another variable, but I keep getting an error. Here is my code:

 

proc iml;
	start new_hand(bet);
	load module = shoe;
	bet = bet;
	cards = shoe(2);
	create hand var {bet cards};
	append;
	return hand;
	finish new_hand;
	store module = new_hand;
	print(new_hand(7));
	quit;

ERROR: Matrix #TEM1001 has not been set to a value

SAS Super FREQ
Posts: 3,619

Re: SAS IML

There is a difference between a SAS data set (which is on disk) and a SAS/IML matrix (which is in RAM).  In general, you want functions to return matrices so that they can be passed along from one function to another.  Data sets are useful when you need to store data to pass to some other SAS procedure (like PROC SGPLOT to create graphics).

 

Are "bet" and "cards" the same dimension? I'll assume that "bet" is a scalar and that the shoe() function returns a row vector so that you can concatenate the cards with the bet:

proc iml;
load module = shoe;

start new_hand(bet);
	cards = shoe(2);
	hand = bet || cards;
	return hand;
finish new_hand;
store module = new_hand;

print (new_hand(7));

Honestly, though, I don't see the point of this function. The calling function is already going to know the value of "bet," since that value was passed in. So why not just return the cards that were generated? Since you already have the cards() function, it seems like the new_hand function doesn't do anything except return cards(2).

 

 

 

Occasional Contributor
Posts: 19

Re: SAS IML

I need the two variables (cards and bet) to be stored in the same data frame because I need to be able to reference them later on in my assignment. Can you create a dataframe that has two variables of different lengths? That's what I was trying to do in my original post.

Super User
Posts: 9,859

Re: SAS IML

Your code looks right. Can you post the data you have ?

 

proc iml;
cards={'aa','bbb','ccc','dd'};
bet={1,2};

create want var {bet cards};
append;
close;
quit;

proc print;run;
Occasional Contributor
Posts: 19

Re: SAS IML

[ Edited ]

I think I know what my issue is. Below is the code for my shoe function:

proc iml;
	start shoe(m);
	use deck;
	read all into deck;
	shoe = sample(deck, m, "Replace");
	return shoe;
	finish shoe;
	store module = shoe;
	quit;

Although this does what I want, it does not return the m number of cards as a matrix, so in my function new_hand, the error is coming from trying to append something that isn't a matrix.

proc iml;
load module = shoe;

start new_hand(bet, m);
	cards = shoe(m);
	create hand var {cards bet};
	append;
	close hand;
	return hand;
	finish new_hand;
	store module = new_hand;
	quit;

Is there a way to save what is created in the shoe function as a matrix?

 

I am recieving this:

ERROR: Matrix #TEM1001 has not been set to a value.

 

However when I look at the hand data set in my directory, it looks how I want. So it is working, but still giving me an error.

SAS Super FREQ
Posts: 3,619

Re: SAS IML

Your problem is that you are trying to return HAND from the second module. HAND is a data set, not a matrix.  You want to return CARDS instead.

 

I don't know how you are storing the deck, but here is some code that you can play with that might help you get on the right track. Notice that I am passing information around as matrices, not as data set. The program reads the deck into a matrix, which is accessible to the SHOE function as a global variable.:

 

data deck;
length card $3.;
input card $ @@;
datalines;
2S 3S 4S 5S 6S 7S 8S 9S 10S JS QS KS AS
2H 3H 4H 5H 6H 7H 8H 9H 10H JH QH KH AH
2D 3D 4D 5D 6D 7D 8D 9D 10D JD QD KD AD
2C 3C 4C 5C 6C 7C 8C 9C 10C JC QC KC AC
;

proc iml;
use deck;
read all var {card} into deck;
close deck;

start shoe(m) global (deck);
	shoe = sample(deck, m, "Replace");
	return shoe;
finish shoe;

start new_hand(bet, m);
	cards = shoe(m);
   return cards;
finish new_hand;

do player = 1 to 5;
   h = new_hand(7, 2);
   print player h;
end;
Occasional Contributor
Posts: 19

Re: SAS IML

What I need to return from the new_hand function needs to contain both the cards AND the amount of the bet. If I just return cards then it doesn't contain the amount of the bet and does me no good.

 

Ideally, I want to return from the new_hand function a matrix or data set (not sure which is the right choice) that contains 2 variables, one is the cards and one is the bet. 

SAS Super FREQ
Posts: 3,619

Re: SAS IML

That's fine, you can return 2 arguments by making 'bet' an input/output argument. As I wrote before:

"The usual way I approach this issue is to pass multiple arguments to the functions.... In SAS/IML,parameters are passed by reference, which means that you can also specify that a module should compute multiple output parameters "  (That underlined phrase is a hyperlink that points to an article about what is means to pass by reference.)

 

start new_hand(bet, m);
	cards = shoe(m);
   bet = bet * 2;       /* you can change bet here */
   return cards;
finish new_hand;

do player = 1 to 5;
   bet = 1 + player;     /* initial bet for each player*/
   h = new_hand(bet, 2); /* bet might change in function */
   print player bet h;
end;

 

SAS Super FREQ
Posts: 3,619

Re: SAS IML

Data sets and matrices are rectangular objects. You can pad shorter variables with missing values to pack into a rectangular structure.  The CREATE/APPEND statement does that automatically when you write to a data set. For a matrix, you would have to do it manually:

proc iml;
long = {1,2,3,4,5,6};
short = {7, 8};

padShort = j(nrow(long), 1, .);  /* create vetor of missing values */
padShort[1:nrow(short)] = short; /* assign nonmissing values */
all = padShort || long;          /* concatenate ontop matrix */
print all;

However, that is not the approach I would take. The usual way I approach this issue is to pass multiple arguments to the functions. The first argument can be a scalar, the second a vector, the third a matrix, etc. In SAS/IML, parameters are passed by reference, which means that you can also specify that a module should compute multiple output parameters 

Ask a Question
Discussion stats
  • 8 replies
  • 674 views
  • 0 likes
  • 3 in conversation