View previous topic :: View next topic
|
Author |
Message |
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Howdy,
Ya never know what will come thru the door . . .
One of the programming groups asked if i knew how to do this using SAS - i don't.
They need to pull a sample from a universe of several million entries. The rules they are to follow (specified by those who receive the sample) is that they are to generate a random number between 1 and n and once they have this initial number, they are to read the data and extract every nth entry.
The Rules document mentions SAS several places and that team lead would like to use it for brownie points.
I can count on less than 1 hand the "things" i've done with SAS and these were clones of something that was already running. Went to the SAS site and their "hits" are more comprehensive than i need. Our forum has over 500 SAS topics, but only 2 contain "random" . . .
What i'd like to do is run a SAS process that takes in a parm or sysin specifying 'n' and "writes" the random number.
Thanks,
d |
|
Back to top |
|
|
Bill O'Boyle
CICS Moderator
Joined: 14 Jan 2008 Posts: 2501 Location: Atlanta, Georgia, USA
|
|
|
|
Dick,
I Googled "SAS Random Number Generator Function" and got several hits, one example using the SAS "RAND" function.
HTH.... |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Code: |
//STEP1 EXEC SAS,PARM='SYSPARM=<value>'
//RANOUT DD DISP=SHR,DSN=....
//SYSIN DD *
DATA _NULL_;
SEED = SUBSTR("&SYSPARM",1)+0 ;
RANVAL = INT(RANUNI(SEED)*N) + 1 ;
FILE RANOUT;
PUT RANVAL ;
|
This code is not tested but other than possible syntax issues it should meet the need. RANUNI returns a uniform random number between 0 and 1. To scale a random number between 0 and 1 to the range M to N, multiply the random number by N, take the integer value of that (which gives a range of 0 to N) and add M to result so the range becomes M to M+N. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Thanks guys,
@Bill - yup, found those and several others that left me thinking Whoa all i wanted was one leetle number
@Robert - ran the code you posted and this is what was returned:
Code: |
The SAS System
44444444444444444444444444444444444444444444444444444444444E884ECE4EAAA89
0000000000000000000000000000000000000000000000000000000000038502120282354
_________________________________________________________________________
.
4444444444444444444444444444444444444444444444444444444444444444444444444
B000000000000000000000000000000000000000000000000000000000000000000000000 |
Multiple runs give the x'4B'. . .
Thanks,
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
The dot means the value is missing. You need to substitute N in the code with whatever your maximum value is. If you did that, add
before the FILE RANOUT; statement so I can see which SAS variable is not defined. That will list all the values in the DATA step on your SAS log. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hi Robert,
Added the _ALL_ and now i get:
Code: |
The SAS System
44444444444444444444444444444444444444444444444444444444444E884ECE4EAAA89
0000000000000000000000000000000000000000000000000000000000038502120282354
_________________________________________________________________________
.
4444444444444444444444444444444444444444444444444444444444444444444444444
B000000000000000000000000000000000000000000000000000000000000000000000000
_________________________________________________________________________
SEED=55 RANVAL=. N=. _ERROR_=0 _N_=1
ECCC7FF4DCDECD744D7446CDDDD67F46D67F4444444444444444444444444444444444444
2554E550915513EB05EB0D59969DE00D5DE10000000000000000000000000000000000000 |
I used 55 for the "seed" value. |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
If you want random numbers in the range 1 to 20, change
Code: |
RANVAL = INT(RANUNI(SEED)*N) + 1 ;
|
to
Code: |
RANVAL = INT(RANUNI(SEED)*20) + 1 ;
|
or you could add
before this statement. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hi Robert,
Here's what did the deed:
Code: |
//SASPROC EXEC PROC=SAS,
// PARM.SAS='SYSPARM=200'
//RANOUT DD SYSOUT=*
//SAS.SYSIN DD *
DATA _NULL_;
SEED = SUBSTR("&SYSPARM",1)+0 ;
RANVAL = INT(RANUNI(SEED)*209) + 1 ;
FILE RANOUT;
PUT RANVAL ;
PUT _ALL_ ;
// |
'Preciate it
Just anticipatin' . . . What if they want the random number to change even if they specify the same seed? As it is now (which is what i expected) running the same seed multpile times returns the same random number.
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Quote: |
What if they want the random number to change even if they specify the same seed? |
The whole point of the seed is that the random number sequence won't change unless the seed changes. I would accomplish what you are saying by doing something like
Code: |
SEED = INT(MOD (TIME(), SEED)) ; |
as the line before RANVAL=. This will cause the seed value to be dependent upon the time of day as well as the parameter, so you will get different random numbers even though the parameter is not changed. |
|
Back to top |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1744 Location: Tirupur, India
|
|
|
|
Hi,
Here is a code similar to Robert's idea using 0 as seed,
When we use 0 as seed, the RANUNI function automatically takes time as the seed and generated random numbers which are truly random.
Code: |
%let sysparm = 20; /* When this parameter is passed via JCL, remove this line. */
data wells;
RANVAL=ceil(ranuni(0)*&sysparm) ;
/* FILE RANOUT; */
put RANVAL;
run; |
Output when the above program was run in a loop for 20 times:
Code: |
16
7
8
12
9
13
16
14
8
18
2
16
4
14
3
13
9
13
4
8
|
Hope it helps, |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Hi Guys,
@Robert
made a slight mod to latest SEED=
Code: |
SEED = INT(MOD (TIME(), SUBSTR("&SYSPARM",1)+0)) ; |
When i used the posted line, i was back to the x'4B'. With the mod, it appears to work as advertised
@Vasanth
Copied in your code as:
Code: |
DATA WELLS;
RANVAL=CEIL(RANUNI(0)*&SYSPARM) ;
FILE RANOUT; */
PUT RANVAL;
PUT _ALL_ ; |
This also generates different random numbers from the same parm.
I'll talk with the people with this "opportunity" and explain they are welcome to both the "same value" code or the "different each run code".
Thanks to you both!
When the scope "creeps" i may be back
d |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Yup, scope has creeped and i'm looking for what (i hope) is a very trivial bit of info.
First, thanks again for all of the help earlier. 'Tis working just as was desired.
However, now the requirement has changed a bit and instead of using sysparm, the value needs to be read from a data file and used in the same way "sysparm" was used originally. Suggestions?
Also, i've been to the SAS site and they sure do have the documentation available - an overwhelming amount. With my extremely limited SAS exposure, i have/had no idea which 1 or few manuals might be good for a SAS beginner (me).
Is there a for-pay book that anyone might recommend? Looks like i'd best prepare for more of these . . .
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Look for The Little SAS Book: A Primer which is a good starting point, albeit a pricy starting point. There's a SAS for Dummies book on Amazon but I haven't looked at it so I'm not sure how good it is. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Thanks Robert,
The Amazon price is now below $40.
Any suggestion on how to use a value from an input file instead of sysparm?
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Code: |
DATA WELLS;
INFILE SEEDFILE ;
INPUT SEEDVAL ;
RANVAL=CEIL(RANUNI(0)*SEEDVAL) ;
FILE RANOUT; */
PUT RANVAL;
PUT _ALL_ |
will work as long as SEEDVAL is something SAS can recognize as a number. JCL would be (using 12345 for the seed)
Code: |
//SEEDFILE DD *
12345
/* |
although SEEDFILE could point to a file, too. |
|
Back to top |
|
|
vasanthz
Global Moderator
Joined: 28 Aug 2007 Posts: 1744 Location: Tirupur, India
|
|
|
|
Hi D,
"Little SAS book" is one of the good SAS tutorials.
I have the "SAS for Dummies" (black and yellow cover with a cartoon guy's face in front) but the book keeps beating around the bush and does not really gets into serious programming whatsoever, lengthy as well.
I have attached one of the PDF(50 actual pages & available free) after which little SAS book can be more useful.
.
The PDF would say "Advanced SAS tutorial" but trust me, its very basic and interesting with examples. It has some information relating to PC SAS, but PC sas and mainframe SAS are the same in terms of program.
Many of my collegues have found it very useful for beginning. Hope it helps some more people. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Thanks again!
Worked like a charm! Both with a dd * and an actual dsn.
Later,
d |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Thanks Vasanth,
I've downloaded the pdf and will check it out.
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Great -- glad to hear it worked. |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Heee's Baaaack . . . .
One (hopefully) last "opportunity" on this (Ha).
My "users" stopped by yesterday and 'splained that what they would really like is the ability to process multiples. I spent time last night looking thru our posts and the internet and did not find an example of SAS code that read an qsam file (with multiple fields).
I seem to recall that at least one of our topics had a SAS external file definition that had individual fields, but i was unable to find it.
Over the weekend, i'll order "the little sas book" and download some more "stuff".
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
If you put multiple values in SEEDFILE in the last code I posted, SAS will read each one and generate a random number. Do you need to be able to write each of these random numbers to an output file as well? |
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
My bad
Yup, i've successfully run multiple input records.
However, I need to break out fields on the same input record(s). The value(s) will not always be in position 1.
So far, i've been able to find/use a numeric value that is not in position 1 (@nnn).
Also needed is a way to generate the random number without the leading zeros suppressed
'Preciate it!
d |
|
Back to top |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8700 Location: Dubuque, Iowa, USA
|
|
|
|
Using a trailing @@ on the INPUT line such as
will cause SAS to start looking for the second value immediately after the end of the first value. Make sure you do NOT have line numbers in your file, though, or the line numbers will be read as data.
Using a Zn. format for the PUT statement will cause SAS to add leading zeroes. If you want the value to be 8 digits wide, for example, use
|
|
Back to top |
|
|
dick scherrer
Moderator Emeritus
Joined: 23 Nov 2006 Posts: 19243 Location: Inside the Matrix
|
|
|
|
Excellent - the Zn. did the trick!
Once again, thanks very much.
d |
|
Back to top |
|
|
Charles Wolters
New User
Joined: 30 Mar 2011 Posts: 48 Location: United States
|
|
|
|
Dick,
I have used the following approach where BOUND is your N value so here I want to select a random number between 1 and 25. Using the PARM keyword I am feeding the value of BOUND to SAS. The RANUNI function activates the SAS random number generator. The value of 959078 is the seed I have given to random number generator and this is arbitrary. The random number is written to the SAS log and I am not sure this is where you want it.
Charles Wolters
//S688CLWX JOB XXXUNKA9,S688CLW,
// MSGCLASS=R,NOTIFY=&SYSUID
// SET BOUND=25
//STEP1 EXEC SAS,PARM='SYSPARM="&BOUND"'
//SYSIN DD *
***PASS INTERVAL FOR RANDOM NUMBER GENERATION ;
DATA _NULL_ ;
RANNUM = INT(&SYSPARM * RANUNI(959078)) + 1 ;
CALL SYMPUT('MYNUM',PUT(RANNUM,8.)) ;
RUN ;
%PUT SELECTED RANDOM NUMBER = &MYNUM ; |
|
Back to top |
|
|
|