Reputation: 11
I have been working on randomly selecting items within an array. Below, I have outlined my process. I have made it to successfully step 6 (with many data checks), but for some reason, when I reference the array, I receive a value of zero. This has been confusing because even when I check the raw sorted data note a certain value, the value retrieved is zero. Additionally, I ran a VNAME to see which variable it was pulling and it corresponded to the correct place within the array. Does anyone know why I am returning a zero value from the array?
*STEP 1: Set all non-codes to zero;
ARRAY CEREAL [337] ha_DTQ02_1-ha_DTQ02_337;
DO i=1 to 337;
if CEREAL[i]=88888.00 THEN CEREAL[i]=0;
END;
*STEP 2: Sort so that all zero values come first and food codes come last;
call SORTN(ha_DTQ02_1-ha_DTQ02_337);
*STEP 3: Rename array in reverse order so that zeros come last and codes are first. Sort function above only works in ascending order;
RENAME ha_DTQ02_1- ha_DTQ02_337=ha_DTQ02_337-ha_DTQ02_1;
*STEP 4: Count number of cereals selected;
ARRAY CEREALS[337]ha_DTQ02_1-ha_DTQ02_337;
NUMCEREALS=0;
DO i=1 to 337;
IF CEREALS[i] NOT IN (.,0) THEN NUMCEREALS+1;
END;
*STEP 5: get a random number between those two numbers- this works just fine;
IF NUMCEREALS NE 0 THEN rand1 = rand('integer', 1, numCereals);
*ensure that your second random number isn't the same as the first random number;
if NUMCEREALS ge 2 then do until(rand2 ne rand1);
rand2 = rand('integer', 1, numCereals);
end;
*STEP 6: Pull value from array using random number.;
Note: This is where I am stuck. I have tried alternative code where I recreated a new array and tried to pull the values from that new array. I have also tried placing the code directly below before closing the do loop. When the code does run, the value for these variables is zero. After many data checks, steps 1-5 work well and achieve their goals.
dtd020Af = CEREALS (rand1);
dtd020Bf = CEREALS (rand2);
OPTIONS NOFMTERR;
run;
Upvotes: 0
Views: 42
Reputation: 27508
You can't rename variables during run-time and reference the value with the new names.
You have declared an ARRAY listing the variables in 1..337 order. Check, that's good. You CAN declare a second ARRAY listing the variables in reverse 337..1 order!
You also do not want to use a variable that might be missing, rand2
, as a index value.
Suggested code:
data have;
call streaminit(123);
do id = 1 to 100;
array X X1-X337;
do over X;
if rand('uniform') < 0.75 then X = 88888;
else
X = rand('integer',1,10);
if id=50 then if _I_ ne 10 then X=88888; else X=5;
end;
OUTPUT;
end;
run;
data want;
set have;
ARRAY CEREAL X1-X337;
DO i=1 to DIM(CEREAL);
if CEREAL[i]=88888.00 THEN CEREAL[i]=0;
END;
* sort the variables that comprise the CEREAL array;
call SORTN(of CEREAL(*));
* second array to reference variables in reverse order;
array CEREAL_REVERSE x337-x1;
* count how many non-missing/non-zero values at the end of the sorted variables;
DO i=1 to DIM(CEREAL);
IF CEREAL_REVERSE[i] IN (.,0) then leave;
NUMCEREALS = i;
END;
IF NUMCEREALS NE 0 THEN rand1 = rand('integer', 1, numCereals);
if NUMCEREALS ge 2 then
do until(rand2 ne rand1);
rand2 = rand('integer', 1, numCereals);
end;
* assign random selection if warranted;
if NUMCEREALS > 0 then dtd020Af = CEREAL_REVERSE (rand1);
if NUMCEREALS > 1 then dtd020Bf = CEREAL_REVERSE (rand2);
run;
Upvotes: 0
Reputation: 27508
The SORTN
call routine needs the OF
operator in order to utilize a name list.
call SORTN(of ha_DTQ02_1-ha_DTQ02_337);
A keen eye on the LOG
window should have shown you the WARNING
3214 call SORTN(ha_DTQ02_1-ha_DTQ02_337);
-----
134
WARNING 134-185: Argument #1 is an expression, which cannot be updated by the SORTN subroutine
call.
Upvotes: 1