Jan's Blog

Programming, SAS

NONMEM ADDL Calculation and Compression in SAS


ADDL represents the number of additional doses that are copies of the current row, with the time since first dose (RTFD) increased at the regular dosing interval (II). This allows for the compression of dose records in the NONMEM dataset. To put it more eloquently:

The NONMEM data item ADDL on a dose record expresses the number of additional implicit doses that should follow at a regular interval II. In the case where explicit doses exist, ADDL supports compacting them into ADDL/II notation.


The gist of calculating ADDL is the following:

For this example, we will focus on compressing explicit doses and we will stick to date-based dosing only. The principles can be easily adjusted for date-and-time-based exposure data. Instead of defining the dosing interval (II) as 24h, we will just define it as 1 day in a macro variable.

%let allowed_dose_delay = 1;

The exposure data will be defined across two subjects, with multiple treatments, multiple dose levels, and occasional gaps between doses exceeding the 1 day window.

data ex;
	format date date9.;
	input usubjid trt $ dose date : date9.;
1 A 50 01JAN1990
1 B 75 02JAN1990
1 A 50 02JAN1990
1 B 100 03JAN1990
1 A 50 03JAN1990
1 B 100 04JAN1990
1 A 50 05JAN1990
1 A 100 06JAN1990
1 B 50 06JAN1990
1 A 100 07JAN1990
1 A 100 08JAN1990
1 A 100 09JAN1990
2 B 50 01JAN1990
2 A 75 02JAN1990
2 B 50 02JAN1990
2 A 100 03JAN1990
2 B 50 03JAN1990
2 B 100 04JAN1990
2 B 50 05JAN1990
2 A 100 06JAN1990
2 B 50 06JAN1990
2 A 100 07JAN1990

proc sort data=ex out=addl_pre;
	by usubjid trt date dose;

After the initial dataset has been populated and sorted, a unique sequence number starting from 1 should be assigned to each treatment within each subject. In addition, a “must_list” variable will be populated with “Y” if:

data addl1;
	set addl_pre;
	by usubjid trt date dose;

	retain seq 1;

	if first.usubjid or first.trt then do;
		must_list = "Y";
		seq = 1;
	else do;
		seq + 1;

	if trt ^= lag(trt) then must_list = "Y";
	if dose ^= lag(dose) then must_list = "Y";
	if date - lag(date) ^= &allowed_dose_delay. then must_list = "Y";

The maximum sequence per subject and treatment should be determined to calculate ADDL for the final, must-list exposure records.

proc sql noprint;
	create table addl2 as
		select *, max(seq) as max_seq
		from addl1
		group by usubjid, trt
		order by usubjid, trt, date

The exposure events are filtered to keep only the “must-list” records. The remaining records will be compressed into the ADDL counter. With real-world data, you may want to add any record linked to PK sampling to the “must-list” group. This can be done by linking the exposure date and time with the sample reference dose date and time, e.g., PC.PCRFTDT.

data addl3;
	set addl2(where=(must_list = "Y"));

Reverse sort the dataset to allow peeking at the next sequence records.

proc sort data=addl3 out=addl4_pre; 
	by descending usubjid descending trt descending date descending seq;

data addl4;
	set addl4_pre;
	by descending usubjid descending trt descending date descending seq;

	next_seq = lag(seq);
	if usubjid ^= lag(usubjid) or trt ^= lag(trt) then next_seq = .;

	proc sort; by usubjid trt date seq;

Finally, ADDL is calculated as the difference between MAX_SEQ and SEQ in the case of the final record, otherwise (NEXT_SEQ – (SEQ + 1)) to ensure we have exclusive bounds between the current and next exposure sequence numbers.

data addl5;
	set addl4;

	if missing(next_seq) then addl = max_seq - seq;
	else addl = next_seq - (seq + 1);

	keep usubjid trt date dose addl;
While not explicitly specified here, our data has II defined as 24 hours or 1 day. In real-world data an II column would be visible in the data.

Provided that your data is well-structured and clean, compressing the exposure records and calculating ADDL is a straightforward task!

Leave a Reply

Back to top