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

I'm working with a dataset with multiple obs per patient (multiple test dates and results). I want to isolate any patient that has had a positive test, then later a negative, then later a positive again among all tests done. It doesn't have to be in this particular order- for example it's OK if patient had a positive, then 3 negatives, then a positive. Or any other possible combination of results...as long as at any time he had a positive, then later a negative, then again a positive. In the example below, patients 1 and 2 should be isolated as they met the criteria. Patient 3 did not as he never got  a second positive after the last negative. Thank you!

 

DATA have;
input patient_id collection_date : $15. test_result : $15.;
datalines;
1 05/18/2015 Positive
1 05/21/2015 Negative
1 08/24/2016 Positive
1 11/01/2016 Negative
1 04/11/2018 Positive
2 01/02/2015 Negative
2 01/10/2016 Positive
2 02/06/2016 Negative
2 03/16/2016 Positive
3 05/21/2016 Positive
3 05/27/2016 Positive
3 01/07/2017 Negative
;
RUN;

 

1 ACCEPTED SOLUTION

Accepted Solutions
japelin
Rhodochrosite | Level 12

I think collection_date is easier to handle with the date type.
(In the following, I've created another date variable.)

 

data next;
  set have;
  coldt=input(collection_date,mmddyy10.);
run;

proc sort data=next;
  by patient_id coldt;
run;
data want;
  set next;
  by patient_id coldt;
  retain flgp flgn flgo;
  if first.patient_id then do;
    flgp=0;
    flgn=0;
    flgo=0;
  end;
       if flgn=0 and test_result='Positive' then flgp=1;
  else if flgp=1 and test_result='Negative' then flgn=1;
  else if flgn=1 and test_result='Positive' then flgo=1;
  /* Enable "and test_result='Positive'" if you want to exclude patients who meet the criteria but test negative again. */
  if flgo=1 /*and test_result='Positive'*/ and last.patient_id then output;
  drop coldt flg:;
run;

View solution in original post

4 REPLIES 4
japelin
Rhodochrosite | Level 12

I think collection_date is easier to handle with the date type.
(In the following, I've created another date variable.)

 

data next;
  set have;
  coldt=input(collection_date,mmddyy10.);
run;

proc sort data=next;
  by patient_id coldt;
run;
data want;
  set next;
  by patient_id coldt;
  retain flgp flgn flgo;
  if first.patient_id then do;
    flgp=0;
    flgn=0;
    flgo=0;
  end;
       if flgn=0 and test_result='Positive' then flgp=1;
  else if flgp=1 and test_result='Negative' then flgn=1;
  else if flgn=1 and test_result='Positive' then flgo=1;
  /* Enable "and test_result='Positive'" if you want to exclude patients who meet the criteria but test negative again. */
  if flgo=1 /*and test_result='Positive'*/ and last.patient_id then output;
  drop coldt flg:;
run;
vegan_renegade
Obsidian | Level 7
Thank you! This worked, although I don't understand the meaning behind each line, starting with the do loop. Would like an explanation of each line if you have time.
japelin
Rhodochrosite | Level 12

How about this?
I put as many comments as I could in each line.

 

data next;
  set have;
  coldt=input(collection_date,mmddyy10.);/* Create a date variable for sorting. */
run;

proc sort data=next;
  by patient_id coldt;/* Sort by patient_id and date */
run;
data want;
  set next;
  by patient_id coldt;
  retain flgp flgn flgo;/* Specify the flag variables flgp, flgn, and flgo with retain so that they remain after the next obs is read. */
  if first.patient_id then do;/* Initialize the flag variable at the first obs of the patient */
    flgp=0;/* 1 If Positive */
    flgn=0;/* 1 if Negative */
    flgo=0;/* 1 if output target  */
  end;
       if flgn=0 and test_result='Positive' then flgp=1;/* Set the flag "flgp" when a Positive is detected. */
  else if flgp=1 and test_result='Negative' then flgn=1;/* Set the flag "flgn" when a Negative is detected after a Positive. */
  else if flgn=1 and test_result='Positive' then flgo=1;/* Set the flag "flgo" if there is a Positive after a Negative */
  /* Enable "and test_result='Positive'" if you want to exclude patients who meet the criteria but test negative again. */
  if flgo=1 /*and test_result='Positive'*/ and last.patient_id then output;/* If the patient is an output target (flgo=1), output the last obs of the patient */
  drop coldt flg:;/* Delete the work variables */
run;
vegan_renegade
Obsidian | Level 7
Yes this is perfect, thank you!

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 4 replies
  • 805 views
  • 1 like
  • 2 in conversation