Bits & Flames bitsandflames/fyron

Clinical DataFrame Operations

fyron.dataframe provides small, explicit helpers for deriving clinical columns from ordinary pandas DataFrames. Use it when you need ICD-10 disease-group indicators, German OPS procedure categories, stable one-hot indicators for delimited code strings, or reusable date/time interval columns before cohort construction, phenotyping, preprocessing, survival analysis, or machine learning.

This module is not a replacement for pandas and it is not a validated terminology ontology. It gives researchers transparent, reviewable feature derivations that can be saved, inspected, and challenged in a study protocol.

Install

bash
uv add fyron

Imports

python
from fyron import dataframe as fdf

API Contract

TopicContract
Input shapeOne-row-per-patient or one-row-per-event DataFrames with code or date columns. Scalar helpers also accept single code strings.
Required columnsCode columns named in the call, date columns for interval helpers, and optional ID columns kept by the caller for audit.
Return shapeDataFrame copies with derived columns, prevalence summary DataFrames, exploded long code tables, or pandas.Series interval outputs.
Saved artifactsSave the enriched cohort table, code prevalence tables, date interval definitions, and the original raw code columns.
Failure modesMissing columns, invalid time units, negative intervals when disallowed, malformed code strings, or overly broad categories requiring clinical review.

When To Use It

TaskHelper
Convert ICD-10 strings into broad comorbidity featuresadd_icd10_disease_groups
Summarize ICD-10 disease-group prevalenceicd10_group_prevalence
Convert German OPS strings into broad procedure categoriesadd_ops_categories
Summarize OPS category prevalenceops_category_prevalence
Parse semicolon-separated code columnssplit_code_string, explode_code_column
Add stable indicators for selected codesadd_code_indicators
Compute days, weeks, months, or years between datesdate_difference, add_date_difference
Compute age at baseline or scan dateage_at_date
Flag events inside an index-relative windowadd_time_window_flag

Study Pattern

In most projects this module is used early, right after extraction and before statistical modeling:

python
from fyron import dataframe as fdf

cohort = fdf.add_icd10_disease_groups(cohort, icd_col="icd10_codes")
cohort = fdf.add_ops_categories(cohort, ops_col="ops_codes")
cohort = fdf.age_at_date(
    cohort,
    birth_date_col="birth_date",
    reference_date_col="index_date",
    output_col="age_at_index",
)

code_qc = fdf.icd10_group_prevalence(cohort)

Save both cohort and code_qc. The enriched cohort becomes the modeling table; the prevalence table becomes a lightweight audit artifact for the methods supplement or internal review.

ICD-10 Disease Groups

ICD-10 helpers use broad pragmatic chapter-style groups such as cancer, cardiovascular, respiratory, gastrointestinal, renal/urologic, trauma, external cause, and healthcare encounter. These are useful for quick cohort description and feature engineering, but they should not replace a study-specific phenotype definition or validated comorbidity score.

python
cohort = fdf.add_icd10_disease_groups(
    cohort,
    icd_col="diagnosis_codes",
    sep=";",
    prefix="icd10_group_",
)

prevalence = fdf.icd10_group_prevalence(cohort)

The output keeps the original diagnosis_codes column and adds binary columns such as icd10_group_cancer, icd10_group_cardiovascular, plus icd10_groups and n_icd10_groups.

Built-In ICD-10 Groups

GroupTypical ICD-10 chapter signal
CancerC*
Benign / In Situ NeoplasmD00-D48
Hematologic / ImmuneD50-D89
InfectiousA*, B*
Endocrine / MetabolicE*
Mental HealthF*
NeurologicalG*
CardiovascularI*
RespiratoryJ*
GastrointestinalK*
DermatologicL*
Musculoskeletal / AutoimmuneM*
Renal / UrologicN*
Obstetric / PerinatalO*, P*
CongenitalQ*
Symptoms / FindingsR*
TraumaS*, T*
Healthcare EncounterZ*
External CauseV*, W*, X*, Y*
Othermalformed or uncategorized non-empty codes

OPS Procedure Categories

German OPS codes are grouped into broad procedure categories: diagnostic procedures, imaging, surgery, medication/therapy, radiation/nuclear medicine, intensive care, rehabilitation, and other. OPS coding can be site-specific, so treat these as transparent research features that still need clinical review.

python
cohort = fdf.add_ops_categories(
    cohort,
    ops_col="ops_codes",
    sep=";",
    prefix="ops_category_",
)

ops_summary = fdf.ops_category_prevalence(cohort)

Use the summary table in supplements or QC notebooks to check whether procedure features match clinical expectations.

Built-In OPS Categories

CategoryTypical OPS chapter signal
Diagnostic Procedures1-*, 2-*
Imaging3-*
Surgery5-*
Medication / Therapy6-*, most 8-* therapy codes
Radiation / Nuclear Medicine7-*
Intensive Care8-98*
Rehabilitation9-*
Othermalformed or uncategorized non-empty codes

Generic Code Columns

Use the generic helpers for medication codes, local registry fields, procedure codes, or any delimited string column where exact code membership matters.

python
long_codes = fdf.explode_code_column(
    cohort,
    code_col="medication_codes",
    output_col="medication_code",
)

cohort = fdf.add_code_indicators(
    cohort,
    code_col="medication_codes",
    codes=["L01XA01", "L01XA02"],
    prefix="atc_",
)

By default, codes are uppercased and spaces are removed. Dots are preserved unless you pass remove_dots=True through normalize_code directly. Preserve the raw source column alongside derived indicators so reviewers can trace the feature.

For multiple local definitions, pass a mapping. This gives stable, readable output names without repeating code lists across notebooks.

python
cohort = fdf.add_code_indicators(
    cohort,
    code_col="procedure_codes",
    codes={
        "has_biopsy": ["1-440", "1-444"],
        "has_resection": ["5-324", "5-325"],
    },
    prefix="proc_",
)

Date And Time Features

Date helpers use the same clinical time-unit convention as cohort endpoint helpers: months are 30.4375 days and years are 365.25 days.

python
cohort = fdf.add_date_difference(
    cohort,
    start_col="baseline_ct_date",
    end_col="surgery_date",
    output_col="days_ct_to_surgery",
    unit="days",
    allow_negative=False,
)

cohort = fdf.age_at_date(
    cohort,
    birth_date_col="birth_date",
    reference_date_col="baseline_ct_date",
    output_col="age_at_ct",
)

cohort = fdf.add_time_window_flag(
    cohort,
    date_col="biopsy_date",
    index_date_col="baseline_ct_date",
    output_col="biopsy_within_30d",
    before=30,
    after=30,
)

add_time_window_flag computes the event date relative to the index date. Negative values are before the index, positive values are after the index.

Function Guide

FunctionPurposeReturns
normalize_codeNormalize one clinical code string.string or None
split_code_stringParse one delimited code cell.list of codes
explode_code_columnConvert a wide delimited code column to one row per code.DataFrame
add_code_indicatorsAdd exact-code binary indicators.DataFrame copy
classify_icd10Classify one ICD-10 code into a broad disease group.group name or None
classify_icd10_stringClassify all ICD-10 codes in one delimited cell.set of group names
add_icd10_disease_groupsAdd ICD-10 disease-group indicator columns.DataFrame copy
icd10_group_prevalenceSummarize ICD-10 group indicator columns.prevalence DataFrame
classify_opsClassify one German OPS code into a broad procedure category.category name or None
classify_ops_stringClassify all OPS codes in one delimited cell.set of category names
add_ops_categoriesAdd OPS category indicator columns.DataFrame copy
ops_category_prevalenceSummarize OPS category indicator columns.prevalence DataFrame
date_differenceCompute interval between two date arrays/scalars.Series
add_date_differenceAdd an interval column to a DataFrame.DataFrame copy
age_at_dateAdd age in years at a reference date.DataFrame copy
add_time_window_flagFlag whether a date falls inside an index-relative window.DataFrame copy

Common Pitfalls

  • Broad ICD-10 and OPS groups are feature-engineering assumptions, not validated disease ontologies.
  • Keep raw code columns and code-system metadata whenever possible.
  • Use prefixed indicator columns to avoid spaces and slashes in downstream ML formulas.
  • Check whether repeated codes should count once per patient or once per event before exploding.
  • Define the index date before creating time-window flags.
  • Use allow_negative=False when a negative interval indicates a data error for the study.
  • FHIR REST extracts source resources that often contain ICD, OPS, medication, and observation codes.
  • Phenotyping builds explicit rule-based patient flags from code, lab, and medication tables.
  • Cohort Tables joins derived features with endpoints and validates cohort shape.
  • Preprocessing QC handles imputation, train/test encoding, and leakage checks after feature derivation.
  • Machine Learning trains and evaluates models once a cohort table and feature matrix are ready.