Skip to content

kusy2009/sdtm-epoch

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sdtm-epoch

GitHub

SDTM EPOCH Derivation Utilities - Multi-language implementations for deriving the EPOCH variable in CDISC SDTM datasets.

Overview

This repository provides derive_epoch() functions in R, Python, and SAS for deriving the EPOCH variable for SDTM datasets. The functions analyze subject event records from the SE (Subject Elements) domain and determine which epoch each record belongs to by comparing reference datetime variables against epoch datetime ranges.

Features

  • ISO 8601 Precision Handling: Properly handles date-only (YYYY-MM-DD), datetime without seconds (YYYY-MM-DDTHH:MM), and full datetime (YYYY-MM-DDTHH:MM:SS) formats
  • Datetime Boundary Resolution: When dates fall exactly on epoch boundaries, uses "tightest SESTDTC match" algorithm (latest start datetime)
  • SDTM-IG Compliant: Pre-study records return missing EPOCH by default, with optional edge case handling
  • Comprehensive Testing: Full test suites in testthat (R), pytest (Python), and native SAS

Repository Structure

sdtm-epoch/
├── r/
│   └── derive_epoch.R           # R implementation
├── python/
│   └── derive_epoch.py          # Python implementation
├── sas/
│   └── derive_epoch.sas         # SAS macro implementation
├── tests/
│   ├── testthat/
│   │   └── test-derive_epoch.R  # R testthat tests
│   ├── pytest/
│   │   └── test_derive_epoch.py # Python pytest tests
│   └── sas/
│       └── test_derive_epoch.sas # SAS test program
├── README.md
├── LICENSE
└── .gitignore

Installation

R

# Source the function directly
source("r/derive_epoch.R")

# Required packages
install.packages(c("dplyr", "cli"))

Python

# Import the function
from python.derive_epoch import derive_epoch

# Required packages
# pip install pandas

SAS

/* Include the macro */
%include "sas/derive_epoch.sas";

Quick Start

R Example

library(dplyr)
source("r/derive_epoch.R")

# Load SE domain (must be named 'SE' in environment)
SE <- data.frame(
  USUBJID = c("S001", "S001"),
  SESTDY = c(1, 30),
  SEENDY = c(29, 60),
  SESTDTC = c("2024-01-04", "2024-02-07T16:10"),
  SEENDTC = c("2024-02-07T16:10", "2025-05-13T15:50"),
  EPOCH = c("SCREENING", "TREATMENT"),
  TAETORD = c(1, 2)
)

# Create input dataset
dm <- data.frame(
  USUBJID = "S001",
  RFSTDTC = "2024-02-07T16:00"
)

# Derive EPOCH
result <- derive_epoch(dm, "RFSTDTC")
# result$EPOCH == "SCREENING" (16:00 is before 16:10 boundary)

Python Example

import pandas as pd
from python.derive_epoch import derive_epoch

# Load SE domain (must be named 'SE' in global namespace)
SE = pd.DataFrame({
    'USUBJID': ['S001', 'S001'],
    'SESTDY': [1, 30],
    'SEENDY': [29, 60],
    'SESTDTC': ['2024-01-04', '2024-02-07T16:10'],
    'SEENDTC': ['2024-02-07T16:10', '2025-05-13T15:50'],
    'EPOCH': ['SCREENING', 'TREATMENT'],
    'TAETORD': [1, 2]
})

# Create input dataset
dm = pd.DataFrame({
    'USUBJID': ['S001'],
    'RFSTDTC': ['2024-02-07T16:00']
})

# Derive EPOCH
result = derive_epoch(dm, 'RFSTDTC')
# result['EPOCH'].iloc[0] == 'SCREENING'

SAS Example

/* SE domain must exist in sdtm library */
libname sdtm "path/to/sdtm";

%include "sas/derive_epoch.sas";

/* Derive EPOCH for AE domain */
%derive_epoch(
    sdtm_in   = sdtm.ae,
    sdtm_out  = ae_with_epoch,
    ref_var   = aestdtc
);

Parameters

Parameter R Python SAS Description
sdtm_in Input SDTM dataset with USUBJID and ref_var
ref_var Reference datetime column (ISO 8601)
handle_edge Handle out-of-range dates (default: FALSE/N)
sdtm_out - - Output dataset name (SAS only)

SE Domain Requirements

The SE (Subject Elements) domain must contain:

  • USUBJID - Unique Subject Identifier
  • SESTDY - SE Start Day
  • SEENDY - SE End Day
  • SESTDTC - SE Start Date/Time (ISO 8601)
  • SEENDTC - SE End Date/Time (ISO 8601)
  • EPOCH - Epoch value
  • TAETORD - Trial Arm Element Order

Datetime Handling

Format Start Datetime End Datetime
YYYY-MM-DD 00:00:00 23:59:59
YYYY-MM-DDTHH:MM :00 appended :59 appended
YYYY-MM-DDTHH:MM:SS As-is As-is

Running Tests

R (testthat)

library(testthat)
library(dplyr)
library(cli)
source("r/derive_epoch.R")
test_file("tests/testthat/test-derive_epoch.R")

Python (pytest)

cd sdtm-epoch
pytest tests/pytest/test_derive_epoch.py -v

SAS

/* Run in SAS environment */
%include "tests/sas/test_derive_epoch.sas";

SDTM-IG Guidance

  • Findings domains: Use --DTC as ref_var (e.g., LBDTC, VSDTC)
  • Interventions/Events domains: Use --STDTC as ref_var (e.g., AESTDTC, EXSTDTC)
  • Pre-study records: Should have null EPOCH (use handle_edge = FALSE)

Contributing

Contributions are welcome! Please ensure:

  1. Tests pass for all three languages
  2. Follow existing code style
  3. Update documentation as needed

Author

Saikrishnareddy Yengannagari - GitHub

License

MIT License - see LICENSE

References

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors