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

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

 

1 ACCEPTED SOLUTION

Accepted Solutions
Tom
Super User Tom
Super User

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;

 

View solution in original post

8 REPLIES 8
mkeintz
PROC Star

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.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Caetreviop543
Obsidian | Level 7

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

mkeintz
PROC Star

Test it and see.

--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
ballardw
Super User

@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


 

Caetreviop543
Obsidian | Level 7

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

Tom
Super User Tom
Super User

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?

 

Tom
Super User Tom
Super User

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;

 

Caetreviop543
Obsidian | Level 7

Thanks Tom! That's extremely helpful; I would have never thought to do it that way. I appreciate it!

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 8 replies
  • 1198 views
  • 0 likes
  • 4 in conversation