- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello,
I need to randomly round a count number to a base of 5, which means a number such as 32 can round down to 30 or up to 35 depending on the probability of rounding up and down. Any idea how to do it in SAS v9.4? Below is the sample of data set.
data table;
input count;
datalines;
23
178
456
8231
;
run;
Thank you very much!
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
That's right. For my project, 1 output is enough instead of 10. 10-time outputs are just for my understanding of concept of random rounding.
Very appreciate!
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Not sure what "the probability of rounding up or down" means, but this ought to be in the running:
numvar = round(numvar, 5);
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
roundedvar = 5 * floor(count/5) + /* start by rounding down */
5 * (rand('uniform')>0.5); /* randomly add five to round up */
Paige Miller
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Hello @Cathy8 and welcome to the SAS Support Communities!
I think @PGStats's solution (which received 9 likes!) in this January thread is likely applicable to your problem, depending on how you define the "probability of rounding up and down."
Here's a combination of that solution (or rather a variant of it) and @Astounding's suggestion:
data want;
call streaminit(27182818);
set table;
rcount=round(count+ifn(rand('uniform')<mod(count,5)/5,2,-2),5);
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
It works. Not sure if that's what I exactly want. Thanks a lot!
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
I interpret the question as "round a number to the nearest unit of 5 with probability proportional to the distance from the number to the possible rounding values."
Thus
31 rounds to 30 with probability 4/5 and rounds to 35 with probability 1/5.
32 rounds to 30 with probability 3/5 and rounds to 35 with probability 2/5.
33 rounds to 30 with probability 2/5 and rounds to 35 with probability 3/5.
34 rounds to 30 with probability 1/5 and rounds to 35 with probability 4/5.
See SAS code for the "random estimator" in the article "Predict a random integer."
I wrote it to round to the nearest integer, but you can just divide your number by 5, round to the nearest integer using the code I provide, and then multiply the result by 5.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thank you very much Rick!
The probability proportion is what I need. I twisted your code posted at Predict a random integer as the below.
%let NumGuesses = 10;
data Guess(keep = x PredRound diffRound PredRand diffRand Frac count k Frac);
set table;
call streaminit(12345);
array prob[4] _temporary_ (0.2, 0.4, 0.6, 0.8); /* P(X=i) */
k = int(count/5)*5;
Frac = (count - k)/10; /* distance from E(X) to x. divided by 10 to fit the Bernoulli */
do i = 1 to &NumGuesses;
PredRound = round(count); /* guess the nearest integer */
PredRand = k + rand("Bern", Frac)*5; /* random guesses between k and k+1, weighted by Frac */
/* The guesses are made. Now generate a new instance of X and compute residual difference */
x = rand("Table", of prob[*]);
diffRound = x - PredRound; /* rounding estimate */
diffRand = x - PredRand; /* unbiased estimate */
output;
end;
;
run;
Seem the PredRand is generated from the Bernoulli distribution; the x is generated from random probability. So I should use x as the random rounding number. Am I right?
I am not sure how to revise x = rand("Table", of prob[*]) for my case. Can you proviea bit more instruction?
Thank you so much!!!!
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
I applaud your effort, but I don't think you quite understood the details of my program. I am assuming this is for an assignment, so let me provide hints instead of an immediate solution:
- Let y be the value you want to round to the nearest multiple of 5.
- Define z = y/5. Your goal is to round z to the nearest integer. You will then multiple that integer by 5 to obtain the result.
- Let L be the integer that is less than or equal to z.
- Then p = z - L is the probability that you will round up.
- For each guess you want to make (up to *NumGuesses), do the following:
- x = L + (random 0 or 1). Hint: Use the Bernoulli distribution with prob p.
- Your guess is 5*x
Now see if you can use those hints to write a SAS program.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Rick for your hint.
Here is my code.
%let NumGuesses = 10;
data method_3;
set death;
z=count/5;
L=int(z);
if mod(count, 5) ne 0 then do;
do i = 1 to &NumGuesses;
if mod(count, 5)=1 then x = L + RAND('BERNoulli',0.8);
if mod(count, 5)=2 then x = L + RAND('BERNoulli',0.6);
if mod(count, 5)=3 then x = L + RAND('BERNoulli',0.4);
if mod(count, 5)=4 then x = L + RAND('BERNoulli',0.2);
y=5*x;
output;
end;
end;
if mod(count, 5)= 0 then do; y=count; output; end;
run;
Any suggestions?
Thank you very much!
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
Should change the probability in rand().
%let NumGuesses = 10;
data method_3;
set death;
z=count/5;
L=int(z);
if mod(count, 5) ne 0 then do;
do i = 1 to &NumGuesses;
if mod(count, 5)=1 then x = L + RAND('BERNoulli',0.2);
if mod(count, 5)=2 then x = L + RAND('BERNoulli',0.4);
if mod(count, 5)=3 then x = L + RAND('BERNoulli',0.6);
if mod(count, 5)=4 then x = L + RAND('BERNoulli',0.8);
y=5*x;
output;
end;
end;
if mod(count, 5)= 0 then do; y=count; output; end;
run;
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
It looks to me like the calculations are correct. The only question I have is whether the numbers that are already multiples of 5 should be output &NumGuesses times instead of once. My guess is that you should output those numbers 10 times as well, but reread the problem specification.
- Mark as New
- Bookmark
- Subscribe
- Mute
- RSS Feed
- Permalink
- Report Inappropriate Content
That's right. For my project, 1 output is enough instead of 10. 10-time outputs are just for my understanding of concept of random rounding.
Very appreciate!