How to Apply CDISC Standards: A Hands-On Clinical SAS Tutorial with Data
  • by Handson
  • August 9, 2026
How to Apply CDISC Standards: A Hands-On Clinical SAS Tutorial with Data

The Clinical Data Interchange Standards Consortium (CDISC) has become a fundamental part of modern clinical research and regulatory data submission. For Clinical SAS programmers, understanding how to apply CDISC standards is much more valuable than simply memorizing SDTM variable names.

In this hands-on tutorial, we will take a small set of fictional clinical trial data and transform it into standardized CDISC SDTM datasets using SAS programming concepts.

The objective is to understand the complete workflow:

Raw Clinical Data → Mapping Specification → SDTM Domain → SAS Program → Validation

The examples use fictional data for educational purposes and should not be treated as a substitute for the applicable CDISC standards, implementation guides, controlled terminology, sponsor specifications, or regulatory requirements.

What Is CDISC?

The Clinical Data Interchange Standards Consortium (CDISC) develops standards that help organizations represent and exchange clinical research data consistently.

CDISC standards cover different stages of the clinical research lifecycle. Important standards for a Clinical SAS programmer include:

  • CDASH

  • SDTM

  • ADaM

  • Define-XML

  • Controlled Terminology

CDISC describes SDTM as a model for organizing and formatting clinical study data, while SDTMIG provides implementation guidance for standard clinical trial tabulation datasets.

A simplified clinical data standards flow is:

Clinical Trial / CRF
        ↓
     CDASH
        ↓
     Raw Data
        ↓
      SDTM
        ↓
      ADaM
        ↓
 Statistical Analysis

The focus of this tutorial is the SDTM portion of this process.


Step 1: Understand the Clinical Trial

Before writing SAS code, a programmer needs to understand the study.

Consider a fictional study:

Study ID: ABC001

Study type: Randomized clinical trial

Treatment groups:

  • Drug A

  • Placebo

Suppose we have three subjects:

Subject Site Treatment Sex Age
001 101 Drug A F 45
002 101 Placebo M 52
003 102 Drug A F 38

The study also collects:

  • Adverse events

  • Vital signs

  • Laboratory results

  • Treatment exposure

Our objective is to convert these raw observations into SDTM domains.

Step 2: Identify the SDTM Domains

The first question a Clinical SAS programmer should ask is:

Where does each piece of clinical information belong?

For this example:

Raw Information SDTM Domain
Subject demographics DM
Treatment administration EX
Adverse events AE
Vital signs VS
Laboratory results LB

Therefore, our project will create:

DM
EX
AE
VS
LB

This is the beginning of the mapping process.

Step 3: Create the Raw Demographic Data

Let's start with a fictional raw demographic dataset.

SUBJECT    SITE    TREATMENT    SEX    AGE
001        101     Drug A       F      45
002        101     Placebo      M      52
003        102     Drug A       F      38

In SAS, we could create this data as:

data raw.dm;
    input subject $ site $ treatment $ sex $ age;
    datalines;
001 101 DrugA   F 45
002 101 Placebo M 52
003 102 DrugA   F 38
;
run;

This is our starting point.


Step 4: Map Raw Variables to SDTM Variables

Now create a mapping specification.

Raw Variable SDTM Variable Transformation
SUBJECT SUBJID Direct mapping
SITE SITEID Direct mapping
TREATMENT ARM Map treatment
SEX SEX Controlled terminology
AGE AGE Direct mapping
Study identifier STUDYID Assigned
Domain DOMAIN Assigned
Subject identifier USUBJID Derived

The important lesson is that SDTM programming is not simply renaming variables.

Some variables are:

  • Directly mapped

  • Derived

  • Assigned

  • Standardized

  • Coded

  • Converted to ISO 8601

  • Controlled using CDISC terminology

Step 5: Create STUDYID

Every study needs a study identifier.

For our example:

STUDYID = ABC001

In SAS:

studyid = "ABC001";

Step 6: Create DOMAIN

For the Demographics domain:

domain = "DM";

The resulting record begins to look like:

STUDYID    DOMAIN
ABC001     DM

Step 7: Create USUBJID

One of the most important identifiers in SDTM is USUBJID, the Unique Subject Identifier.

Suppose the sponsor's study specification defines USUBJID as:

STUDYID-SITEID-SUBJID

Then:

ABC001-101-001
ABC001-101-002
ABC001-102-003

In SAS:

usubjid = catx("-", studyid, siteid, subject);

The resulting data becomes:

STUDYID DOMAIN USUBJID
ABC001 DM ABC001-101-001
ABC001 DM ABC001-101-002
ABC001 DM ABC001-102-003

The exact USUBJID construction should always follow the study-specific specification.

Step 8: Create the DM Dataset

Now we can build a simplified DM dataset.

data sdtm.dm;
    set raw.dm;

    length studyid $20
           domain  $2
           usubjid $40
           arm     $20;

    studyid = "ABC001";
    domain  = "DM";

    siteid = site;

    subjid = subject;

    usubjid = catx("-", studyid, siteid, subjid);

    if treatment = "DrugA" then arm = "Drug A";
    else if treatment = "Placebo" then arm = "Placebo";

    keep studyid domain usubjid subjid siteid sex age arm;
run;

This illustrates an important Clinical SAS programming principle:

The raw dataset is transformed into a standardized dataset rather than being used directly for analysis.

Step 9: Add Treatment Exposure Data

Now suppose the raw exposure data is:

Subject Start Date End Date Dose Unit
001 2026-01-10 2026-02-09 100 mg
002 2026-01-10 2026-02-09 0 mg
003 2026-01-12 2026-02-11 100 mg

This information belongs to the EX domain.

The mapping might be:

Raw Variable SDTM Variable
Subject USUBJID
Start Date EXSTDTC
End Date EXENDTC
Dose EXDOSE
Unit EXDOSU
Treatment EXTRT

Step 10: Convert Dates to ISO 8601

SDTM date/time variables commonly use ISO 8601 representations.

For example:

2026-01-10

A SAS date can be converted using:

exstdtc = put(start_date, yymmdd10.);

Similarly:

exendtc = put(end_date, yymmdd10.);

CDISC guidance also discusses ISO 8601 date/time and interval representations in SDTMIG v3.4 and SDTM v2.0.

Step 11: Create the EX Dataset

A simplified SAS program could be:

data sdtm.ex;
    set raw.exposure;

    length studyid $20
           domain  $2
           usubjid $40
           extrt   $40
           exdosu  $20
           exstdtc exendtc $20;

    studyid = "ABC001";
    domain  = "EX";

    usubjid = catx("-", studyid, siteid, subject);

    extrt = treatment;

    exdose = dose;
    exdosu = unit;

    exstdtc = put(start_date, yymmdd10.);
    exendtc = put(end_date, yymmdd10.);

    keep studyid domain usubjid extrt exdose exdosu
         exstdtc exendtc;
run;

Step 12: Add Adverse Event Data

Suppose the raw adverse event data is:

Subject Event Start Date End Date Severity
001 Headache 2026-01-15 2026-01-17 Mild
002 Nausea 2026-01-20 2026-01-21 Moderate
003 Headache 2026-01-18 2026-01-20 Mild

The information belongs to the AE domain.

The mapping could be:

Raw Variable SDTM Variable
Event AETERM
Start Date AESTDTC
End Date AEENDTC
Severity AESEV
Subject USUBJID

Step 13: Understand AETERM and AEDECOD

This is an important concept for beginners.

Suppose the investigator reports:

Head pain

The reported term can be represented as:

AETERM = Head pain

The coded medical terminology may result in:

AEDECOD = HEADACHE

Therefore:

AETERM represents the reported term, while AEDECOD represents the standardized coded term.

The coding process depends on the study's medical coding conventions and applicable dictionaries.

A programmer should not simply assume that AETERM and AEDECOD are always identical.

Step 14: Create AESEQ

Many SDTM domains require a sequence number to distinguish multiple records for the same subject.

For example:

Subject 001

AESEQ = 1
AESEQ = 2
AESEQ = 3

A simple SAS approach is:

by usubjid;

if first.usubjid then aeseq = 0;
aeseq + 1;

The exact sequence-generation approach should follow the study's programming specifications.

Step 15: Create the AE Dataset

A simplified example:

proc sort data=raw.ae out=ae_sort;
    by subject start_date;
run;

data sdtm.ae;
    set ae_sort;

    by subject;

    length studyid $20
           domain  $2
           usubjid $40
           aeterm  $200
           aedecod $200
           aestdtc aeendtc $20
           aesev   $20;

    studyid = "ABC001";
    domain  = "AE";

    usubjid = catx("-", studyid, siteid, subject);

    if first.subject then aeseq = 0;
    aeseq + 1;

    aeterm = event;

    if upcase(event) = "HEADACHE" then
        aedecod = "HEADACHE";
    else if upcase(event) = "NAUSEA" then
        aedecod = "NAUSEA";

    aestdtc = put(start_date, yymmdd10.);
    aeendtc = put(end_date, yymmdd10.);

    aesev = propcase(severity);

    keep studyid domain usubjid aeseq
         aeterm aedecod aestdtc aeendtc aesev;
run;

This is an educational example. Production medical coding should follow the study's coding process and applicable dictionary.


Step 16: Create Vital Signs Data

Suppose the raw vital-sign data is:

Subject Visit Test Result Unit
001 Baseline Systolic BP 120 mmHg
001 Baseline Diastolic BP 78 mmHg
002 Baseline Systolic BP 130 mmHg
002 Baseline Diastolic BP 82 mmHg
003 Baseline Systolic BP 118 mmHg
003 Baseline Diastolic BP 76 mmHg

This information belongs to the VS domain.

Step 17: Understand TEST and TESTCD

The Findings domains commonly use a pair of variables such as:

VSTESTCD
VSTEST

For example:

VSTESTCD = SYSBP
VSTEST   = Systolic Blood Pressure

and:

VSTESTCD = DIABP
VSTEST   = Diastolic Blood Pressure

The TESTCD is a short standardized code, while TEST provides the descriptive test name.

Controlled terminology and applicable domain guidance should be used rather than inventing values arbitrarily.

Step 18: Create VS

A simplified SAS program might be:

data sdtm.vs;
    set raw.vitals;

    length studyid $20
           domain $2
           usubjid $40
           vstestcd $8
           vstest $40
           vsorresu $20
           vsstresu $20;

    studyid = "ABC001";
    domain = "VS";

    usubjid = catx("-", studyid, siteid, subject);

    if upcase(test) = "SYSTOLIC BP" then do;
        vstestcd = "SYSBP";
        vstest = "Systolic Blood Pressure";
    end;

    else if upcase(test) = "DIASTOLIC BP" then do;
        vstestcd = "DIABP";
        vstest = "Diastolic Blood Pressure";
    end;

    vsorres = strip(result);
    vsorresu = unit;

    vsstresn = input(result, best.);
    vsstresc = strip(result);
    vsstresu = unit;

    keep studyid domain usubjid vstestcd vstest
         vsorres vsorresu vsstresc vsstresn vsstresu;
run;

This demonstrates the distinction between the original result and the standardized result.

Step 19: Understanding ORRES and STRESC/STRESN

Findings domains often distinguish between:

ORRES

The result as originally collected.

STRESC

The standardized character result.

STRESN

The standardized numeric result, where appropriate.

For example:

VSORRES  = 120
VSSTRESC = 120
VSSTRESN = 120

For a numeric finding, VSSTRESN can be particularly useful for standardized numerical representation.

Step 20: Create Laboratory Data

Suppose we have:

Subject Test Result Unit
001 Hemoglobin 13.5 g/dL
002 Hemoglobin 14.1 g/dL
003 Hemoglobin 12.8 g/dL
001 ALT 25 U/L
002 ALT 31 U/L
003 ALT 22 U/L

These records belong to the LB domain.

A simplified mapping is:

Raw SDTM
Test LBTEST
Test Code LBTESTCD
Result LBORRES
Unit LBORRESU
Numeric Result LBSTRESN
Subject USUBJID

Step 21: Apply Controlled Terminology

Controlled Terminology is one of the most important parts of CDISC implementation.

CDISC defines Controlled Terminology as standardized expressions and valid values used with data items in CDISC-defined datasets. CDISC maintains this terminology with the National Cancer Institute's Enterprise Vocabulary Services.

For example, instead of allowing multiple inconsistent representations:

Male
male
M
Man

the applicable controlled terminology should determine the appropriate submission representation.

The same principle applies to:

  • Sex

  • Race

  • Ethnicity

  • Severity

  • Relationship

  • Outcome

  • Units

  • Findings tests

  • Other controlled values

Controlled terminology should be checked against the applicable current release rather than copied from an old project.

CDISC's March 27, 2026 terminology release updated SDTM and other terminology files, illustrating why programmers need to verify the terminology version used by the study.

Step 22: Build a Complete SDTM Mapping Table

A practical mapping specification might look like this:

Raw Domain Raw Variable SDTM Domain SDTM Variable Transformation
Demographics SUBJECT DM SUBJID Direct
Demographics SITE DM SITEID Direct
Demographics SEX DM SEX Controlled terminology
Demographics AGE DM AGE Direct
Exposure TREATMENT EX EXTRT Standardize
Exposure DOSE EX EXDOSE Direct
Exposure START_DATE EX EXSTDTC ISO 8601
Exposure END_DATE EX EXENDTC ISO 8601
AE EVENT AE AETERM Direct
AE EVENT AE AEDECOD Medical coding
AE START_DATE AE AESTDTC ISO 8601
AE SEVERITY AE AESEV Controlled terminology
Vital Signs TEST VS VSTEST Standardize
Vital Signs RESULT VS VSORRES Direct
Laboratory TEST LB LBTEST Standardize
Laboratory RESULT LB LBORRES Direct

This mapping specification becomes the blueprint for SAS programming.

Step 23: Understand the Complete SDTM Programming Architecture

A real-world Clinical SAS project is generally more complex than the examples above.

A simplified architecture is:

Raw / EDC Data
      |
      v
Data Review
      |
      v
Mapping Specification
      |
      v
SDTM Programming
      |
      v
SDTM Domains
      |
      +---- DM
      +---- AE
      +---- EX
      +---- VS
      +---- LB
      |
      v
Quality Control
      |
      v
Validation
      |
      v
Define-XML / Metadata
      |
      v
Regulatory Submission

Step 24: Validate the SDTM Dataset

Programming is not complete when the SAS dataset is created.

The programmer should check:

Dataset-level checks

  • Correct domain name

  • Correct dataset structure

  • Correct variable names

  • Correct variable labels

  • Correct variable types

  • Correct lengths

  • Appropriate sort order

  • Appropriate keys

Record-level checks

  • Duplicate records

  • Missing identifiers

  • Incorrect dates

  • Invalid controlled terminology

  • Unexpected values

  • Incorrect sequence numbers

  • Inconsistent subject identifiers

Cross-domain checks

For example:

DM.USUBJID
        ↓
AE.USUBJID
        ↓
EX.USUBJID
        ↓
VS.USUBJID
        ↓
LB.USUBJID

A subject appearing in AE, EX, VS or LB should generally be traceable to the appropriate study subject information.

Step 25: Example Validation Checks in SAS

Check for duplicate subjects in DM:

proc sort data=sdtm.dm out=dm_check nodupkey;
    by usubjid;
run;

Check missing USUBJID:

proc sql;
    select *
    from sdtm.ae
    where missing(usubjid);
quit;

Check unexpected AE severity values:

proc freq data=sdtm.ae;
    tables aesev;
run;

Check domain values:

proc freq data=sdtm.ae;
    tables domain;
run;

These simple checks are useful during development, although production validation normally includes substantially more extensive checks.

Step 26: CDISC Is More Than SDTM

One common misconception among beginners is:

CDISC = SDTM

That is not correct.

CDISC is a broader standards ecosystem.

For a Clinical SAS programmer, the important components include:

CDISC
 |
 +-- CDASH
 |
 +-- SDTM
 |
 +-- ADaM
 |
 +-- Define-XML
 |
 +-- Controlled Terminology
 |
 +-- Therapeutic Area Standards

CDISC states that its foundational standards form the basis of an end-to-end standards suite, while therapeutic-area standards extend the foundational standards for disease-specific data.


Step 27: SDTM vs ADaM

It is important to understand the difference.

SDTM

The primary objective is to organize clinical study data into standardized tabulation structures.

ADaM

The primary objective is to create analysis-ready datasets with traceability to SDTM and the underlying data.

A simplified relationship is:

RAW DATA
   ↓
SDTM
   ↓
ADaM
   ↓
Tables, Listings & Figures

For example:

Raw Laboratory Data
        ↓
       LB
        ↓
   ADLB
        ↓
Lab Tables / Analysis

Step 28: Hands-On Exercise for Clinical SAS Students

If you are learning Clinical SAS, do not stop after reading the examples.

Create your own mini clinical trial.

Create 20 subjects

Include:

SUBJECT
SITE
SEX
AGE
TREATMENT

Create adverse events

Include:

SUBJECT
EVENT
START_DATE
END_DATE
SEVERITY

Create vital signs

Include:

SUBJECT
VISIT
TEST
RESULT
UNIT

Create laboratory data

Include:

SUBJECT
TEST
RESULT
UNIT

Then create:

DM
AE
EX
VS
LB

using SAS.

Step 29: Build Your Own Mapping Specification

Before writing code, create a spreadsheet with columns such as:

Raw Dataset
Raw Variable
SDTM Domain
SDTM Variable
Source/Derivation
Controlled Terminology
Algorithm
Comments

For example:

RAW_AE
EVENT
AE
AETERM
Direct Mapping
-
-
Reported event term

and:

RAW_AE
SEVERITY
AE
AESEV
Mapping
CDISC CT
-
Standardize severity

This exercise teaches an extremely important real-world skill:

SDTM programming begins with understanding and documenting the mapping, not with writing SAS code.

Step 30: What a Clinical SAS Programmer Should Learn

A strong CDISC-focused Clinical SAS programmer should understand:

SAS

  • DATA step

  • PROC SQL

  • PROC SORT

  • PROC TRANSPOSE

  • MERGE

  • SET

  • BY-group processing

  • Arrays

  • Functions

  • Formats

  • Macro programming

Clinical Research

  • Clinical trial terminology

  • Visits

  • Treatment

  • Randomization

  • Adverse events

  • Laboratory assessments

  • Vital signs

  • Medical history

  • Concomitant medications

  • Exposure

CDISC

  • CDASH

  • SDTM

  • SDTMIG

  • ADaM

  • Controlled Terminology

  • Define-XML

  • Therapeutic Area User Guides

Programming

  • Raw-to-SDTM mapping

  • Derivations

  • ISO 8601 dates

  • Sequence generation

  • Controlled terminology

  • Cross-domain validation

  • Traceability

  • Quality control

Common Mistakes Beginners Make

Mistake 1: Learning Variable Names Without Understanding the Data

Knowing that AETERM exists is not enough.

You need to understand what the clinical event represents.

Mistake 2: Treating SDTM as a Rename Exercise

SDTM programming involves:

Mapping
+
Derivation
+
Standardization
+
Coding
+
Controlled Terminology
+
Validation

Mistake 3: Ignoring the SDTMIG

The SDTM model and implementation guide should be used together. CDISC describes SDTMIG as the guide for the organization, structure and format of standard clinical trial tabulation datasets.

Mistake 4: Using Old Terminology

Controlled terminology changes over time.

Always verify the applicable release.

Mistake 5: Creating Dates That Were Never Collected

If a date is incomplete or missing, the programmer should follow the applicable standard and study specification rather than inventing information.

Mistake 6: Using SUPPQUAL for Everything

Supplemental qualifiers should be used only when appropriate. First determine whether the information belongs in an existing standard variable, domain, or another supported structure.

A Complete Learning Workflow

A useful way to learn CDISC through Clinical SAS is:

1. Learn Clinical Trial Concepts
              ↓
2. Learn Base SAS
              ↓
3. Learn CDISC Fundamentals
              ↓
4. Study SDTMIG
              ↓
5. Learn SDTM Domains
              ↓
6. Practice Mapping
              ↓
7. Write SAS Programs
              ↓
8. Create SDTM Datasets
              ↓
9. Validate
              ↓
10. Learn ADaM
              ↓
11. Learn Define-XML
              ↓
12. Practice Complete Projects

Applying the Clinical Data Interchange Standards Consortium (CDISC) standards is a practical skill that combines clinical knowledge, data standards and SAS programming.

The most effective way to learn is not to memorize hundreds of SDTM variables. Instead, start with real-world-style raw data, understand what each observation means, determine the correct SDTM domain, prepare a mapping specification, write the SAS transformation, apply controlled terminology and finally validate the resulting dataset.

A beginner should start with the core domains:

DM → AE → EX → VS → LB → CM → MH → DS

and gradually move toward more complex domains and standards.

CDISC's current standards ecosystem continues to evolve, so Clinical SAS programmers should always verify the applicable SDTM model, implementation guide, controlled terminology release, therapeutic-area guidance and regulatory requirements for the project. CDISC currently lists SDTM v2.1 as a released model, while SDTMIG v3.4 is the published human clinical-trial implementation guide and is documented for use with SDTM v2.0.

For anyone preparing for a career as a Clinical SAS Programmer, SDTM Programmer or CDISC Programmer, hands-on raw-to-SDTM programming practice is one of the best ways to turn theoretical CDISC knowledge into job-ready skills.