Brian
Brian

Reputation: 11

Problem: Referencing Array Value, but Returning Zero

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

Answers (2)

Richard
Richard

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

Richard
Richard

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

Related Questions