BookmarkSubscribeRSS Feed
RJY9
Fluorite | Level 6

Hi SMEs, 

 

I am seeking your help to resolve the issues I am facing with the derived visit.
I have attached my_output.xlsx and i_need.xlsx.
The file my_output.xlsx was generated using the SAS code below; however, I need the output to match i_need.xlsx.
Logic implemented:
Week 1 to Week 12 (weekly): when 1 < ADY ≤ 84

Week 1 is derived by taking the worst AVAL from Day 1 to Day 7
Continue similarly up to Week 12 (Day 78 to Day 84)

Week 15 to End of Treatment day. (every 3 weeks): when 85 ≤ ADY ≤ EOTDY

Week 15 is derived by taking the worst AVAL from Day 85 to Day 105. Repeat this process every 3 weeks until the end of treatment day. (EOTDY). 

The above logic is used to derive the worst value per USUBJID / PARAMCD / AVISITN.
For these derived records, DTYPE = WOCF is assigned and appended to the original dataset.
I have created a new variable, NEW_AVISITN, to implement this logic without affecting the existing AVISITN. However, I am not getting the expected values.

Example: I am getting two records for this below PARMCD and avisitn. 
 
101ABCD02W2025-03-14T16:56:009Week 957354WOCF

Slightly severe

2
101ABCD02W2025-03-16T18:02:009Week 959354WOCFSevere3
101ABCD02W2025-04-04T17:45:0012Week 1278354WOCFNot severe1
101ABCD02W2025-04-05T18:46:0012Week 1279354WOCF

Slightly severe

2


data test1;
set test;
by usubjid avisitn;

retain max_ady;

/* Calculate maximum ADY for each subject on first observation */
if first.usubjid then do;
max_ady = .;
end;

/* Track the maximum ADY value */
if not missing(ady) then do;
max_ady = max(max_ady, ady);
end;

/* Derive visit number and visit name for every observation */
if not missing(ady) then do;
eotdy_value = coalesce(eotdy, max_ady);

if 1 < ady <= 84 then do;
/* Week 1 to Week 12 (every week) when 1 < ADY <= 84 */
/* Day 1-7 = Week 1, Day 8-14 = Week 2, ..., Day 78-84 = Week 12 */
new_avisitn = ceil((ady - 1) / 7);
new_avisit = catx(" ", "Week", put(new_avisitn, best.));
end;
else if not missing(eotdy_value) and 85 <= ady <= eotdy_value then do;
/* After Week 12 every 3 weeks when 85 <= ADY <= EOTDY */
/* Day 85-105 = Week 15, Day 106-126 = Week 18, Day 127-147 = Week 21, etc. */
/* Formula: Week = 15 + floor((ady - 85) / 21) * 3 */
new_avisitn = 15 + floor((ady - 85) / 21) * 3;
new_avisit = catx(" ", "Week", put(new_avisitn, best.));
end;
else do;
call missing(new_avisitn, new_avisit);
end;
end;
else do;
call missing(new_avisitn, new_avisit);
end;
output;
run;

 
%macro wocf(paramcd, paramcd_w);
  proc sql;
    create table &paramcd_w._ as 
    select * from test1
    where not missing(avalc) and paramcd = "&paramcd"
    order by usubjid, new_avisitn, aval descending;
  quit;
 
  data &paramcd_w._1;
    set &paramcd_w._;
    by usubjid new_avisitn descending aval;
    if first.new_avisitn;
  run;
 
 
  data &paramcd_w._2;
    length param $200.;
    set &paramcd_w._1;
    dtype = "WOCF";
    param = "&param_desc";
    PARAMCD = "&paramcd_w";
PARAMTYP = "DERIVED";
    drop aval;
  run;
%mend wocf;
 
/* Call the macro for each parameter */
%wocf(ABCD0102, ABCD02W);
%wocf(ABCD0103, ABCD03W);
%wocf(ABCD0105, ABCD05W );
%wocf(ABCD0106, ABCD06W);
 
data derived;
set ABCD02W_2 ABCD03W_2 ABCD05W_2 ABCD06W_2;
run;
 **adding derived records to the original data set**
data combi;
set test1 derived;
run;

Could you please let me which mistake I am doing here or please provide me a simple solution for this problem.

4 REPLIES 4
ballardw
Super User

Many users here don't want to download Excel files because of virus potential, others have such things blocked by security software. Also if you give us Excel we have to create a SAS data set and due to the non-existent constraints on Excel data cells the result we end up with may not have variables of the same type (numeric or character) and even values.

 

You also do not provide any STARTING data at all. As a minimum we would need a working data step that creates a TEST data set that will yield a similar behavior to your problem. The data step code should be pasted into a text or code box, opened on the forum by clicking on either the </> or "running man" icon above the main message window. These boxes will prevent the forum software from reformatting code such as by removing indentation if any was used and has been known to introduce artifacts into code so that it will not run as pasted.

 

Another advantage to the data step is that we can see the names and properties of variables without even running code. Sometimes that is sufficient to answer some questions.

 

Something else that would be helpful would be to describe what you want help with. Is it only the assignment of the visit number as implied by your subject is there something involving AVAL because you mention "worst Aval" but do not define that anywhere in the problem. And if that is in the example output you show it isn't labeled so we can't tell.

 

At which step is your i_need supposed to generated? Since your code doesn't mention that name for a data set the step(s) in question are a bit obtuse.

Also, the "logic" throws out a lot of apparent time intervals but not a clear explanation of what the intervals are used for.  

It may not hurt to define what "week" means to you as SAS has some function that are more direct interval calculations. Though I suspect that anything using a changing length and thinking of it as "week" is problematic along those lines.

 

Without starting data I can see a couple of places that could result in unexpected results.

The most obvious would be having more than one missing ADY value sequentially or identical values of ADY, presumably across whatever PARAMCD is. Which could be occurring on the same date but at different times of day.

Another is where you take the full TEST1 data set and then append records using SET statement. I would almost think that a MERGE on subjid and avistn (or other identifying variables) would make more sense if the purpose is just to add one number.

There are also places that you assign missing to the new_avist and new_avistn variables. Missing is smaller than all other values so the order of processing in the SQL portion of that macro may not be as expected.

 

Tom
Super User Tom
Super User

You posted two outputs without any inputs.  How can we know what you started with? How can we test code without any inputs?

 

What exactly are you having trouble with?  

 

Is it the grouping of the data into the time periods you described?  Are your 3 week groupings at the end disjoint or overlapping?  That is do you want weeks 16 to 18 after the grouping of weeks 13 to 15? Or instead do you want a three week window from 14 to 16  and then 15 to 17, etc  If the former then what VISITN*VISIT combination do you want store in the dataset for those three week summary stats?  Is it Week 13? Or Week 15? Or something else?

 

Is it the calculation of the summary stat for the grouped values that is causing you trouble?

 

Is it the addition of extra observations to store those derived summary stats?

 

 

Note that spreadsheets are great for doing spreadsheet things, but they are terrible for sharing SAS data.  And do you really need to share almost 4,000 observations of data covering 21 weeks to demonstrate the issue you are having?

 

RJY9
Fluorite | Level 6

Thank you so much for your quick response. I will keep in mind that no excel sheets will be attached in the future for any posts. 

I really appreciate your help. 

I need to derive the worst AVAL per USUBJID / PARAMCD / AVISITN. To get the worst AVAL value. For these derived records, DTYPE = WOCF is assigned, new PARMACD wit suffix of "W" to be assigned and appended to the original dataset. To derive worst record I need to consider the below logic.

Week 1 to Week 12 (weekly): when 1 < ADY ≤ 84
Derive by taking the worst AVAL from Day 1 to Day 7
Continue similarly up to Week 12 (Day 78 to Day 84)

Week 15 to End of Treatment (every 3 weeks): when 85 ≤ ADY ≤ EOTDY
Derive by taking the worst AVAL from Day 85 to Day 105
Repeat this process every 3 weeks until the end of treatment.

Here is the source data. 

USUBJIDPARAMCDADTMAVISITNAVISITADYEOTDYDTYPEAVALCAVAL
101ABCD01022025-01-20T12:54:001Week 14354 Slightly severe2
101ABCD01022025-01-21T07:52:001Week 15354 Slightly severe2
101ABCD01022025-01-22T07:16:001Week 16354   
101ABCD01022025-01-23T12:09:001Week 17354   
101ABCD01022025-01-24T17:15:002Week 28354   
101ABCD01022025-01-26T13:10:002Week 210354 Severe3
101ABCD01022025-01-28T11:09:002Week 212354 Severe3
101ABCD01022025-01-30T14:04:002Week 214354 Slightly severe2
101ABCD01022025-02-01T09:23:003Week 316354 Slightly severe2
101ABCD01022025-02-02T19:56:003Week 317354 Slightly severe2
101ABCD01022025-02-03T14:48:003Week 318354 Slightly severe2
101ABCD01022025-02-04T13:22:003Week 319354 Slightly severe2
101ABCD01022025-02-06T18:44:003Week 321354 Slightly severe2
101ABCD01022025-02-08T18:09:004Week 423354 Slightly severe2
101ABCD01022025-02-09T17:24:004Week 424354 Not severe1
101ABCD01022025-02-10T16:40:004Week 425354 Not severe1
101ABCD01022025-02-11T19:27:004Week 426354 Not severe1
101ABCD01022025-02-12T15:52:004Week 427354   
101ABCD01022025-02-13T17:30:004Week 428354   
101ABCD01022025-02-14T16:52:005Week 529354   
101ABCD01022025-02-15T12:33:005Week 530354   
101ABCD01022025-02-16T12:48:005Week 531354   
101ABCD01022025-02-17T14:52:005Week 532354   
101ABCD01022025-02-18T16:06:005Week 533354   
101ABCD01022025-02-19T13:28:005Week 534354   
101ABCD01022025-02-20T14:57:005Week 535354   
101ABCD01022025-02-21T20:02:006Week 636354   
101ABCD01022025-02-22T10:01:006Week 637354   
101ABCD01022025-02-24T17:57:006Week 639354   
101ABCD01022025-02-25T17:27:006Week 640354   
101ABCD01022025-02-26T22:05:006Week 641354   
101ABCD01022025-02-27T18:11:006Week 642354   
101ABCD01022025-02-28T12:29:007Week 743354   
101ABCD01022025-03-01T12:15:007Week 744354   
101ABCD01022025-03-02T10:07:007Week 745354   
101ABCD01022025-03-03T17:29:007Week 746354   
101ABCD01022025-03-04T16:35:007Week 747354   
101ABCD01022025-03-05T15:40:007Week 748354   
101ABCD01022025-03-06T18:23:007Week 749354   
101ABCD01022025-03-07T09:35:008Week 850354   
101ABCD01022025-03-08T14:16:008Week 851354   
101ABCD01022025-03-09T15:13:008Week 852354   
101ABCD01022025-03-10T18:24:008Week 853354   
101ABCD01022025-03-11T11:34:008Week 854354 Not severe1
101ABCD01022025-03-12T12:41:008Week 855354 Slightly severe2
101ABCD01022025-03-13T16:57:008Week 856354 Slightly severe2
101ABCD01022025-03-14T16:56:009Week 957354 Slightly severe2
101ABCD01022025-03-15T17:32:009Week 958354 Slightly severe2
101ABCD01022025-03-16T18:02:009Week 959354 Severe3
101ABCD01022025-03-17T18:32:009Week 960354 Slightly severe2
101ABCD01022025-03-18T18:21:009Week 961354 Slightly severe2
101ABCD01022025-03-19T21:29:009Week 962354 Slightly severe2
101ABCD01022025-03-21T16:19:0010Week 1064354   
101ABCD01022025-03-22T17:55:0010Week 1065354   
101ABCD01022025-03-23T16:05:0010Week 1066354   
101ABCD01022025-03-24T21:32:0010Week 1067354   
101ABCD01022025-03-25T11:38:0010Week 1068354   
101ABCD01022025-03-26T17:03:0010Week 1069354   
101ABCD01022025-03-27T11:55:0010Week 1070354   
101ABCD01022025-03-28T09:27:0011Week 1171354   
101ABCD01022025-03-29T19:18:0011Week 1172354   
101ABCD01022025-03-31T17:05:0011Week 1174354   
101ABCD01022025-04-01T18:25:0011Week 1175354   
101ABCD01022025-04-02T16:02:0011Week 1176354   
101ABCD01022025-04-03T21:57:0011Week 1177354   
101ABCD01022025-04-04T17:45:0012Week 1278354 Not severe1
101ABCD01022025-04-05T18:46:0012Week 1279354 Slightly severe2
101ABCD01022025-04-06T18:10:0012Week 1280354 Not severe1
101ABCD01022025-04-08T12:00:0012Week 1282354 Slightly severe2
101ABCD01022025-04-09T13:22:0012Week 1283354 Not severe1
101ABCD01022025-04-10T17:56:0012Week 1284354 Slightly severe2
101ABCD01022025-04-11T19:29:0013Week 1385354 Not severe1
101ABCD01022025-04-12T15:53:0013Week 1386354 Not severe1
101ABCD01022025-04-13T20:18:0013Week 1387354 Not severe1
101ABCD01022025-04-14T18:54:0013Week 1388354   
101ABCD01022025-04-15T19:18:0013Week 1389354   
101ABCD01022025-04-16T18:08:0013Week 1390354   
101ABCD01022025-04-17T10:32:0013Week 1391354   
101ABCD01022025-04-18T16:57:0014Week 1492354   
101ABCD01022025-04-19T13:51:0014Week 1493354   
101ABCD01022025-04-20T16:46:0014Week 1494354   
101ABCD01022025-04-21T16:08:0014Week 1495354 Not severe1
101ABCD01022025-04-22T17:21:0014Week 1496354 Slightly severe2
101ABCD01022025-04-23T20:51:0014Week 1497354 Slightly severe2
101ABCD01022025-04-24T19:23:0014Week 1498354 Slightly severe2
101ABCD01022025-04-25T18:44:0015Week 1599354 Severe3
101ABCD01022025-04-26T18:48:0015Week 15100354 Severe3
101ABCD01022025-04-30T14:04:0015Week 15104354 Severe3
101ABCD01022025-05-01T13:08:0015Week 15105354 Slightly severe2
101ABCD01022025-05-02T09:40:0016Week 16106354 Not severe1
101ABCD01022025-05-04T20:07:0016Week 16108354 Slightly severe2
101ABCD01022025-05-05T19:17:0016Week 16109354 Slightly severe2
101ABCD01022025-05-06T16:55:0016Week 16110354 Not severe1
101ABCD01022025-05-07T18:16:0016Week 16111354 Slightly severe2
101ABCD01022025-05-08T09:45:0016Week 16112354 Not severe1
101ABCD01022025-05-09T21:46:0017Week 17113354 Slightly severe2
101ABCD01022025-05-10T17:54:0017Week 17114354 Slightly severe2
101ABCD01022025-05-11T22:10:0017Week 17115354 Slightly severe2
101ABCD01022025-05-12T16:03:0017Week 17116354 Slightly severe2
101ABCD01022025-05-13T16:51:0017Week 17117354 Slightly severe2
101ABCD01022025-05-15T10:08:0017Week 17119354 Slightly severe2
101ABCD01022025-05-19T16:08:0018Week 18123354 Slightly severe2
101ABCD01022025-05-20T16:59:0018Week 18124354 Slightly severe2
101ABCD01022025-05-21T19:34:0018Week 18125354 Slightly severe2
101ABCD01022025-05-22T19:53:0018Week 18126354 Slightly severe2
101ABCD01022025-05-23T17:50:0019Week 19127354 Slightly severe2
101ABCD01022025-05-25T20:24:0019Week 19129354 Slightly severe2
101ABCD01022025-05-26T14:53:0019Week 19130354 Not severe1
101ABCD01022025-05-27T16:31:0019Week 19131354 Not severe1
101ABCD01022025-05-28T15:13:0019Week 19132354 Not severe1
101ABCD01022025-05-29T08:43:0019Week 19133354 Not severe1
101ABCD01022025-05-30T21:46:0020Week 20134354 Not severe1
101ABCD01022025-05-31T20:23:0020Week 20135354   
101ABCD01022025-06-02T18:46:0020Week 20137354   
101ABCD01022025-06-03T19:11:0020Week 20138354   
101ABCD01022025-06-04T18:58:0020Week 20139354   
101ABCD01022025-06-05T20:52:0020Week 20140354   
101ABCD01022025-06-06T17:41:0021Week 21141354   
Ksharp
Super User

Assuming I understood what you mean.

 

data have;
infile cards truncover expandtabs dlm=' ';
input USUBJID	(PARAMCD	ADTM) (:$40.)	AVISITN 	AVISIT	&$20. ADY	EOTDY		AVALC &$20. 	AVAL;
cards;
101	ABCD0102	2025-01-20T12:54:00	1	Week 1	 4	354	 	Slightly severe	 2
101	ABCD0102	2025-01-21T07:52:00	1	Week 1	 5	354	 	Slightly severe	 2
101	ABCD0102	2025-01-22T07:16:00	1	Week 1	 6	354	 	 	 
101	ABCD0102	2025-01-23T12:09:00	1	Week 1	 7	354	 	 	 
101	ABCD0102	2025-01-24T17:15:00	2	Week 2	 8	354	 	 	 
101	ABCD0102	2025-01-26T13:10:00	2	Week 2	 10	354	 	Severe	 3
101	ABCD0102	2025-01-28T11:09:00	2	Week 2	 12	354	 	Severe	 3
101	ABCD0102	2025-01-30T14:04:00	2	Week 2	 14	354	 	Slightly severe	 2
101	ABCD0102	2025-02-01T09:23:00	3	Week 3	 16	354	 	Slightly severe	 2
101	ABCD0102	2025-02-02T19:56:00	3	Week 3	 17	354	 	Slightly severe	 2
101	ABCD0102	2025-02-03T14:48:00	3	Week 3	 18	354	 	Slightly severe	 2
101	ABCD0102	2025-02-04T13:22:00	3	Week 3	 19	354	 	Slightly severe	 2
101	ABCD0102	2025-02-06T18:44:00	3	Week 3	 21	354	 	Slightly severe	 2
101	ABCD0102	2025-02-08T18:09:00	4	Week 4	 23	354	 	Slightly severe	 2
101	ABCD0102	2025-02-09T17:24:00	4	Week 4	 24	354	 	Not severe	 1
101	ABCD0102	2025-02-10T16:40:00	4	Week 4	 25	354	 	Not severe	 1
101	ABCD0102	2025-02-11T19:27:00	4	Week 4	 26	354	 	Not severe	 1
;

proc format;
invalue fmt
1=1
2=2
3=3
4=4
5=5
6=6
7=7
8=8
9=9
10=10
11=11
12=12
13-15=13
16-18=14
19-21=15
22-24=16
25-27=17
28-30=18
;
data have2;
set have;
id=input(AVISITN,fmt.);
run;
proc sql;
create table want as
select * from have2
 group by  USUBJID ,PARAMCD ,id
  having AVAL =max(AVAL );
quit;

Catch up on SAS Innovate 2026

Nearly 200 sessions are now available on demand in the Innovate Hub.

Watch 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.

SAS Training: Just a Click Away

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

Browse our catalog!

Discussion stats
  • 4 replies
  • 114 views
  • 0 likes
  • 4 in conversation