Hi,
I am trying to create 10 tertile variables (TERT1-TERT10), which based on a variable titled PA_AVG on a five point scale, increase by 0.1, and have lower bound second tertile cut offs starting at 2.5, and ending at 3.4. The second tertile upper bound cutoffs start at 3.5 and end at 4.4, increasing by .10.
So, category one in TERT1 would be 0 to 2.4, category two 2.5 to 3.5, and category three, 3.6 to five. Category one in TERT2 would be 0<CAT_ONE<2.6, category two, 2.6<=CAT_TWO<=3.6, and category three, 3.6<CAT_THREE<=5, and so on until TERT10 with a second tertile cut off of 3.4 and 4.4 has been completed.
I am using a nested do loop, but the code isn’t executing (it just keeps running):
data temp;
set rank_tert;
do I=2.5 to 3.4 by 0.1;
do J=3.5 to 4.4 by 0.1;
do TERT=1 to 10 by 1;
if 0<PA_AVG<(I) then TERT=1;
else if (I)<=PA_AVG<=(J) then TERT=2;
else TERT=3;
end;
end;
end;
keep PID_PDE TERT1-TERT10;
run;
Not sure what I am doing wrong, but it may have something to do with how I am creating the 'TERT' variable? Thanks in advance for any help!
Emily
Assuming you want to slide your window to the right by one tenth so that you get ten windows you could do something like this.
This will create temporary arrays to store the bounds. It stores the bounds as integers to take advantage of the integer range specifications to make it easier to specify the bounds as initial vlaues for the array. Just remember to divide by ten when comparing the actual values.
To set TERT values to 0,1,2 you can take advantage of SAS evaluating boolean expressions to 0/1. So if it is in the middle group it is greater than lower bound but not greater than upper bound only one of the two expressions is true and the result is 1. But if it falls in the higher group then both are true so the result is 2.
data temp;
set rank_tert;
array tert (10) ;
array lower (10) _temporary_ (25:34);
array upper (10) _temporary_ (35:44);
do i=1 to dim(tert);
tert(i)= (pa_avg >= lower(i)/10) + (pa_avg > upper(i)/10);
end;
drop i;
run;
You are assigning TERT a value of 1,2, or 3 inside a loop that is defined as "DO TERT=1 to 10". As a result the terminating condition of the loop (TERT>10) is never attained.
Ok, thanks that makes sense.
So, is this correct?
data temp;
set rank_tert;
array tert(i) TERT1-TERT10;
do I=2.5 to 3.4 by 0.1;
do J=3.5 to 4.4 by 0.1;
do i=1 to 10;
if 0<PA_AVG<(I) then tert(i)=1;
else if (I)<=PA_AVG<=(J) then tert(i)=2;
else tert(i)=3;
end;
end;
end;
keep PID_PDE TERT1-TERT10;
run;
Thanks
Test it and see.
@Caetreviop543 wrote:
Ok, thanks that makes sense.
So, is this correct?
data temp;
set rank_tert;
array tert(i) TERT1-TERT10;
do I=2.5 to 3.4 by 0.1; <= If this is an upper case i
do J=3.5 to 4.4 by 0.1;
do i=1 to 10; <= you'll have issues because of this i , k would be more traditional
if 0<PA_AVG<(I) then tert(i)=1;
else if (I)<=PA_AVG<=(J) then tert(i)=2;
else tert(i)=3;
end;
end;
end;
keep PID_PDE TERT1-TERT10;
run;
Thanks
Thank you for your reply, ballardw.
I did change the initial from i to K, however, I received an error saying "Mixing of implicit and explicit array subscripting is not allowed."
I think it's because I included the array reference for only one variable, then tried to incorporate two stand-alone do statements. Ideally, I would like to create the tert variables without an array reference. Not sure if that's possible...
Thanks
Emily
This statement is not clear and the code you attempted is even more confusing.
I am trying to create 10 tertile variables (TERT1-TERT10), which based on a variable titled PA_AVG on a five point scale, increase by 0.1, and have lower bound second tertile cut offs starting at 2.5, and ending at 3.4. The second tertile upper bound cutoffs start at 3.5 and end at 4.4, increasing by .10.
Please post input and output data.
It does not look you have much data, but if you do limit it to just enough values/variables to demonstrate the problem you are having.
What I got from your question is that you want to create 10 variables from one. Not sure how the ten variables relate to the concept of TERTILEs which would imply transforming a continuous variable into three categories. How to you get to 10 from 3?
The second sentence makes it seem like you want to define multiple different pairs of cutoff values. Sounds like want the lower bound to range from 2.5 to 3.4 by 0.1 and the upper bound to range from 3.5 to 4.4 by 0.1. Do they move together so that you generate 10 pairs?
lower_start=2.5;
upper_start=3.5;
do diff=0.0 to 0.9 by 0.1 ;
lower=lower_start+diff;
upper=upper_start+diff;
output;
end;
or independently so that you generate 10*10=100 pairs?
do lower=2.5 to 3.4 by 0.1 ;
do upper=3.5 to 4.4 by 0.1 ;
output;
end;
end;
Once you have these 10 or 100 sets of cut-off pairs how are you then going to apply them to your measured variable?
Assuming you want to slide your window to the right by one tenth so that you get ten windows you could do something like this.
This will create temporary arrays to store the bounds. It stores the bounds as integers to take advantage of the integer range specifications to make it easier to specify the bounds as initial vlaues for the array. Just remember to divide by ten when comparing the actual values.
To set TERT values to 0,1,2 you can take advantage of SAS evaluating boolean expressions to 0/1. So if it is in the middle group it is greater than lower bound but not greater than upper bound only one of the two expressions is true and the result is 1. But if it falls in the higher group then both are true so the result is 2.
data temp;
set rank_tert;
array tert (10) ;
array lower (10) _temporary_ (25:34);
array upper (10) _temporary_ (35:44);
do i=1 to dim(tert);
tert(i)= (pa_avg >= lower(i)/10) + (pa_avg > upper(i)/10);
end;
drop i;
run;
Thanks Tom! That's extremely helpful; I would have never thought to do it that way. I appreciate it!
Are you ready for the spotlight? We're accepting content ideas for SAS Innovate 2025 to be held May 6-9 in Orlando, FL. The call is open until September 25. Read more here about why you should contribute and what is in it for you!
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.