BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
superbug
Quartz | Level 8

@novinosrin 

 

a while ago, you helped about pick 2 people from a certain number of people. Now if I want to choose 4 people from a certain number of people, I am trying to modify the code you helped, but there are error messages, could you help please. Below is the code for picking 4 people from a certain number of people, but it doesn't work, please help.  Thanks much!

 

data want;
set have;
array c col:;
length cat $30 Pair $20;
do _i=1 to dim(c)-1;
do _j=_i+1 to dim(c);
do _m=_j+1 to dim(c)+1;
do _n=_m+1 to dim(c)+2;
k1=c(_i);
k2=c(_j);
k3=c(_m);
k4=c(_n);
Pair=catx('_','Pair',_i,_j,_m,_n);
if k1=k2=k3=k4=itemkey then cat="same resp and all correct";
else if k1=k2=k3=k4^=itemkey then cat="same resp and all wrong";
else if _i=itemkey or _j=itemkey or _m=itemkey or _n=itemkey then cat="different resp and one of them correct";
else cat="different resp and all wrong";
output;
end;
end;
end;
end;
keep itempos itemkey cat pair;
run;

1 ACCEPTED SOLUTION

Accepted Solutions
ballardw
Super User

 

Your two do loops starting here:

do _m=_j+1 to dim(c)+1;
do _n=_m+1 to dim(c)+2;

both attempt to use values of array C with the loop counter _m and _n being larger than the number of elements in the array C. The Dim function returns the number of elements in an array. So when you use dim(c)+1 that is more than number of elements.

 

Guessing because I have no actual data but something similar to this might might work:

do _i=1 to dim(c)-3;
do _j=_i+1 to dim(c)-2;
do _m=_j+1 to dim(c)-1;
do _n=_m+1 to dim(c);

but this will fail if there are fewer than 4 elements in the array.

 

 

View solution in original post

6 REPLIES 6
Patrick
Opal | Level 21

@superbug wrote:

 

....

, but there are error messages, 

.....


What are the errors? Post the SAS log.

superbug
Quartz | Level 8

@Patrick 

Thanks for the reply!

I have 352 columns, I want to pick 4 columns, that is, combination of 4 from 352.

The error message is "ERROR: Array subscript out of range at line 63 column 7", line 63 is  "k4=c(_n);" in the code.

 

Reeza
Super User

Post your code and the full log from the code. 

Exactly where the error occurs helps with the debugging process.

 


@superbug wrote:

@novinosrin 

 

a while ago, you helped about pick 2 people from a certain number of people. Now if I want to choose 4 people from a certain number of people, I am trying to modify the code you helped, but there are error messages, could you help please. Below is the code for picking 4 people from a certain number of people, but it doesn't work, please help.  Thanks much!

 

data want;
set have;
array c col:;
length cat $30 Pair $20;
do _i=1 to dim(c)-1;
do _j=_i+1 to dim(c);
do _m=_j+1 to dim(c)+1;
do _n=_m+1 to dim(c)+2;
k1=c(_i);
k2=c(_j);
k3=c(_m);
k4=c(_n);
Pair=catx('_','Pair',_i,_j,_m,_n);
if k1=k2=k3=k4=itemkey then cat="same resp and all correct";
else if k1=k2=k3=k4^=itemkey then cat="same resp and all wrong";
else if _i=itemkey or _j=itemkey or _m=itemkey or _n=itemkey then cat="different resp and one of them correct";
else cat="different resp and all wrong";
output;
end;
end;
end;
end;
keep itempos itemkey cat pair;
run;


 

ballardw
Super User

 

Your two do loops starting here:

do _m=_j+1 to dim(c)+1;
do _n=_m+1 to dim(c)+2;

both attempt to use values of array C with the loop counter _m and _n being larger than the number of elements in the array C. The Dim function returns the number of elements in an array. So when you use dim(c)+1 that is more than number of elements.

 

Guessing because I have no actual data but something similar to this might might work:

do _i=1 to dim(c)-3;
do _j=_i+1 to dim(c)-2;
do _m=_j+1 to dim(c)-1;
do _n=_m+1 to dim(c);

but this will fail if there are fewer than 4 elements in the array.

 

 

superbug
Quartz | Level 8

@ballardw 

Thanks much for the help.

SAS is running after incorporating the codes you suggested, but it turned out before SAS finish running the code, there is "disk out of space" message, so SAS stopped there and can't continue. How can I make the code more efficient and at the same time delete temporary SAS files generated in the "..user-->temp-->SAS temporary file"?

thanks!

novinosrin
Tourmaline | Level 20

HI @superbug  Sorry couldn't find time to get on here yesterday. The weekend chores+some sleep after all. Anyways, you had mentioned -"Now if I want to choose 4 people from a certain number of people".

This makes certain number of people as N.

Choosing 4 from N, makes it N choose 4. 

 

Therefore, the fundamental understanding we need is the possible combinations can start with N>=4 and r(choice) =4.

When N=4 and choice(r)=4, you will have have just one combination. 

 

With that said, let's begin some understanding using COMB function to see the number of combinations for N starting from 4...... and let's stop at 10 to not get the example unwieldy.

data numofcombs_check;
 do n=4 to 10;
  numofcombs=comb(n,4);
  output;
 end;
run;
n numofcombs 
4 1 
5 5 
6 15 
7 35 
8 70 

That makes sense and also gives us an idea what approach we need to take. Since the choice is 4, we absolutely need 4 temporary variables to get the varying combination depending on the value of N.

Let's mark those 4 temp variables as _i, _j_,_k,_l  with _ prefix to enable as to drop easy later. This practice is called Dorfmanism : ) of course used by everybody, but why dorfmanism is becoz Paul Dorfman uses all automatic _ variables as key strokes more than anybody.  

 

From here on, the logic is simple, to choose 4(r), N can only have values >=4. All, you need to remember is, for every unit increment of N, you would need to make sure to increment the stop value of _i by 1. Example,


data want;
 _n=4;/*for every unit increment of N */
 do _i=1 to 1;/*make sure to increment the stop values by 1*/
  do _j=_i+1 to _n-2;
   do _k=_j+1 to _n-1;
    do _l=_k+1 to _n;
     output;
    end;
   end;
  end;
 end;
run;

/*Increment N by 1 and i by 1*/
/*so 4 is 5, and 1 becomes 2*/
data want2;
 _n=5;/*for every unit increment of N */
 do _i=1 to 2;/*make sure to increment the stop value by 1*/
  do _j=_i+1 to _n-2;
   do _k=_j+1 to _n-1;
    do _l=_k+1 to _n;
     output;
    end;
   end;
  end;
 end;
run;
/*And likewise try incrementing N and stop value of I for experiment purpose*/

That does the logic. For concatenation, I am sure you should be able to type/manage yourself with a catx function. All you need to is , reference the array element values, using the combination values of i,j,k,l. If you are unable to, feel free to let us know. 

 

I hope the above helps. Kind regards!

 

PS I could have answered in your other post. However, you did the right thing in opening a new thread coz one a particular question is solved, it's better to not mess that one with addendums. So with that acknowledgement, I am responding here. That was to do with pairs, this is slightly different. 🙂

 

 

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 6 replies
  • 789 views
  • 2 likes
  • 5 in conversation