MS-DRG (Medicare Severity Diagnosis-Related Groups)
The federal inpatient payment classification system that maps each hospital stay to one of roughly 770 groups — defined by principal diagnosis, procedures, secondary diagnoses (complication/comorbidity severity), and patient attributes — each carrying a relative weight that, multiplied by a hospital-specific base rate, determines Medicare prospective payment for the admission.
In plain language
When a Medicare patient is discharged from a hospital, every diagnosis and procedure from that stay is fed into a grouping program that outputs a single code — the MS-DRG — which tells Medicare how much to pay the hospital. Think of it as a price tag calculated from the patient's main problem, any complications or serious side conditions, and the procedures performed. Researchers use these codes to build groups of similar hospitalizations (for example, all knee-replacement stays), to measure how complex a patient's hospital stay was, and — when actual dollar amounts are unavailable — to estimate the cost of a stay by multiplying the DRG's published resource weight by a standard dollar base rate. The key caveat: the code is assigned to the final discharge record, not to mid-stay billing, and it only exists for acute inpatient stays paid by Medicare's hospital payment system.
MS-DRG
(Medicare Severity Diagnosis-Related Groups) is the classification engine at the center of Medicare's Inpatient Prospective Payment System (IPPS). For every inpatient discharge, a grouper algorithm — a deterministic decision tree published annually by CMS — consumes the coded claim (principal diagnosis, up to 25 secondary diagnoses with present-on-admission flags, ICD-10-PCS procedure codes, discharge status, age, and sex) and assigns a single integer DRG. That DRG carries a relative weight — a national index of resource intensity normalized so that a weight of 1.0 represents the average Medicare inpatient case. Payment = weight × hospital-specific base rate (adjusted for wage index, teaching status, disproportionate share, and outlier thresholds). In FY 2025 the national operating base rate is roughly $6,900; a weight-2.0 DRG therefore generates approximately $13,800 in operating payment before local adjustments. The grouper, relative weight tables, and the CC/MCC lists are republished each fiscal year (effective October 1) and are downloadable without charge from CMS.
Structure: MDC → surgical/medical partition → base-DRG severity triplets
The classification has a three-level hierarchy. At the top, every DRG belongs to one of 25 Major Diagnostic Categories (MDCs) corresponding to body systems or clinical situations (e.g., MDC 5 = Diseases and Disorders of the Circulatory System; MDC 14 = Pregnancy, Childbirth, and the Puerperium). Within each MDC, the grouper first tests whether an OR-qualifying ICD-10-PCS procedure was performed, routing the stay to the surgical partition (e.g., CABG, joint replacement) or the medical partition (diagnosis-driven, no qualifying procedure). Within the surgical or medical partition, most base-DRG families are subdivided into a severity triplet: DRG n (with MCC), DRG n+1 (with CC), and DRG n+2 (without CC or MCC). The canonical teaching example is the heart failure family: DRG 291 (heart failure and shock with MCC), DRG 292 (with CC), and DRG 293 (without CC or MCC). Relative weights for this family in FY 2025 are approximately 2.21, 1.44, and 1.06, respectively — a 2-fold payment spread across the same principal diagnosis depending on whether the patient has serious comorbidities (MCCs) such as acute kidney failure or respiratory failure. CC/MCC determination is driven by the secondary diagnoses that survive present-on-admission (POA) screening: diagnoses that were not present at admission are excluded from CC/MCC capture to deter hospitals from counting hospital-acquired conditions as severity.
CC and MCC lists — and why they drift
CMS publishes the full CC and MCC lists in its IPPS final rule each year. Codes move between the MCC, CC, and non-CC lists with each annual update, sometimes driven by clinical recalibration and sometimes by administrative or coding-industry feedback. This severity drift means that a condition flagged as an MCC in FY 2015 may drop to CC status in FY 2020 without any change in patient health — creating a spurious longitudinal trend in severity-adjusted analyses that cross those fiscal years. Studies using DRG severity tier as a covariate across more than one or two fiscal years should map the underlying diagnosis codes to a fixed CC/MCC version rather than relying on the year-of-discharge grouper assignment.
History and the 2007–2008 version break
The concept of grouping hospital cases by resource intensity was developed at Yale by Robert Fetter and colleagues in the 1970s; CMS (then HCFA) implemented DRG-based prospective payment in October 1983 (Public Law 98-21). The original system was revised many times, but a structural break occurred with the introduction of MS-DRGs in FY 2008 (effective October 1, 2007). Where the pre-2008 system had roughly 538 DRGs with limited severity differentiation, MS-DRGs expanded to roughly 745 groups, adding the three-way CC/MCC severity partition to most base-DRG families. Any longitudinal RWE study that spans the 2007–2008 transition faces a classification break — the same patient with the same diagnoses maps to a different DRG before and after the transition — and must use underlying diagnosis and procedure codes rather than DRG number to build a consistent cohort definition across the break. A second major structural break occurred with the ICD-10-CM/PCS transition on October 1, 2015 (v33+): the entire grouper logic was re-mapped to ICD-10 codes, and ICD-9-era grouper crosswalks are approximate at best.
APR-DRG — the proprietary alternative
Many Medicaid programs, commercial payers, and research databases (including HCUP State Inpatient Data) use All Patient Refined DRGs (APR-DRGs), developed by 3M (now Solventum). APR-DRGs add a four-level severity of illness (SOI) subclass and a separate four-level risk of mortality (ROM) subclass, providing finer clinical stratification. The critical operational distinction: CMS MS-DRGs are defined in public manuals and free software downloadable from CMS; APR-DRGs are a licensed, proprietary product — the code lists, grouper logic, and weights are not public, making full replication in a research context dependent on the licensed grouper engine. When HCUP NIS or SID data report APR-DRG SOI/ROM, researchers should cite the 3M APR-DRG software version rather than treating it as equivalent to MS-DRG. The two systems assign different group numbers to the same discharge; they are not interchangeable as covariates or cohort identifiers.
RWE applications: five core uses
(1) Hospitalization costing when paid amounts are unavailable. The DRG relative weight, multiplied by a national or facility-specific base rate, provides a standardized cost proxy for inpatient stays. This is widely used when the research database carries institutional claims without adjudicated dollar amounts (e.g., certain HCUP files or facility data). The proxy flattens within-DRG variation — two patients in DRG 292 with identical weights receive the same proxy cost regardless of actual resource use — but it is reproducible and externally anchored. (2) Case-mix and severity adjustment. Including DRG relative weight, DRG severity tier, or MDC category as a covariate adjusts for the clinical complexity of the index hospitalization in comparative analyses of readmission, mortality, or post-acute cost. (3) Cohort identification. DRGs define clinically coherent cohorts: "any lower-extremity joint replacement DRG" (469–470), "any heart failure DRG" (291–293), "any pneumonia DRG" (193–195). This is often cleaner than a broad ICD-10 code list for inpatient events because the grouper has already resolved diagnosis + procedure combinations into a single clinical label. (4) Readmission rate denominators. CMS's Hospital Readmission Reduction Program (HRRP) measures 30-day readmission rates following index admissions in specific DRG families (heart failure, pneumonia, COPD, hip/knee replacement). Research replicating or benchmarking HRRP measures must use the same DRG-based denominator logic. (5) Hospital benchmarking and market basket research. DRG relative weights are the national standard for comparing case-mix index across hospitals or over time, and serve as the denominator in payer contracting research.
Pros, cons, and trade-offs
- vs ICD-10 diagnosis-code-only cohort identification: A DRG-defined cohort has already resolved the procedure vs. diagnosis ambiguity (e.g., a hip fracture treated medically vs. one treated with arthroplasty routes to different DRGs) and has applied the MDC exclusion rules. Cost: the grouper assignment is per-discharge and only available on inpatient institutional claims — it does not exist on professional or outpatient claims. Prefer DRG-based cohort definition for inpatient studies where the procedure / treatment delivered is part of the phenotype; use ICD codes directly for outpatient, cross-setting, or pre-admission windows. - vs DRG relative weight as cost proxy vs observed paid/allowed amounts: The weight proxy is standardized, reproducible, and available even when dollar amounts are missing; it avoids adjudication-lag problems. Cost: it flattens within-DRG variation — actual costs for a weight-1.5 DRG can vary threefold — and it ignores outlier payments, transfer adjustments, and disproportionate-share top-ups that affect actual hospital revenue. Use weight as proxy when actual amounts are unavailable or unstandardized; use actual allowed amounts when they are trustworthy and the research question requires patient-level precision. - vs APR-DRG for severity adjustment: APR-DRG SOI/ROM provides four severity tiers vs. the MS-DRG three, giving finer clinical stratification, and APR-DRGs are used by Medicaid in many states and by HCUP files, so they may be the only system available for a given data source. Cost: APR-DRG is proprietary and requires a license; it is not reproducible from public documentation; and comparing results across studies using MS-DRG vs. APR-DRG is non-trivial. Prefer MS-DRG when replicability and transparency are required and when working with Medicare FFS data; use APR-DRG when the data source provides it and cross-institutional comparisons within a system using APR-DRGs are the goal. - vs Elixhauser or Charlson comorbidity scores for severity adjustment: Comorbidity scores capture the patient's baseline disease burden from any diagnoses present in the baseline period. DRG severity tier captures only the CC/MCC complexity of the index hospitalization. They are orthogonal dimensions. Use DRG severity for adjustment within a hospitalization type; use comorbidity scores for baseline adjustment in the pre-admission or washout window; pair both when studying outcomes after an index hospitalization.
When to use
Use MS-DRG when the unit of analysis is an inpatient hospitalization paid under Medicare IPPS: to identify cohorts by procedure and diagnosis type, to adjust for case-mix severity, to proxy inpatient costs, to replicate or benchmark CMS quality programs, or to stratify patients by the severity of their index admission. Use it also as a filter to ensure that claims labeled "inpatient" are from acute-care DRG-paid stays and not from long-term acute care hospitals (LTACHs) or inpatient psychiatric facilities (IPFs), which use separate payment systems and will not have IPPS DRGs.
When NOT to use — and when it is actively misleading or dangerous
- DRG assignment from interim claims (mid-stay). The grouper assigns a DRG to the final discharge claim, not to interim bill types (bill type 0111, 0117). If your extract includes interim inpatient claims, the DRG on those records is provisional or absent; never use interim claim DRGs as if they were final. Always use the discharge claim (bill type 0112 or the final status indicator). - Treating DRG severity tier as a measure of patient health rather than coding practice. Hospitals run active CC/MCC capture programs that mine records for secondary diagnoses that qualify as CCs or MCCs. When coding intensity increases over time (as it did substantially in the early MS-DRG era and again after widespread adoption of EHR documentation tools), the fraction of cases landing in the MCC tier rises without any change in patient health. A longitudinal trend in severity tier is therefore partly a coding-practice trend, not purely a clinical one. Do not interpret year-over-year DRG severity upshift as evidence that patients are becoming sicker. - Using DRG relative weight as a cost proxy for non-IPPS settings. DRG weights are calibrated to Medicare FFS acute-care inpatient costs. Applying them to commercial claims (which have different negotiated rates and patient demographics), to LTACH or rehabilitation stays, or to outpatient services introduces systematic bias. For non-Medicare populations, use the payer-specific allowed amount or a commercial analogue (e.g., an All-Patient DRG weight set calibrated to commercial data). - Crossing the FY2008 or ICD-10 version break without harmonization. A DRG number in FY 2006 is not the same clinical group as the same number in FY 2009 (post-MS-DRG redesign), and neither maps reliably to the ICD-10-era DRG. Trend studies must anchor to principal diagnosis and procedure code rather than DRG number. - Using DRG to identify episodes in Medicare Advantage. MA encounter data may carry a plan-assigned or estimated DRG that does not result from full adjudication under IPPS grouper logic, may be absent entirely, or may reflect a plan's internal risk-adjustment coding. MA-sourced DRGs should not be pooled with FFS DRGs as if they are equivalent. Restrict to Medicare FFS (Parts A/B) or explicitly document and test the MA DRG derivation. - Treating a single DRG number as a clinical phenotype without checking for MDC migration. Occasional annual updates move a diagnosis to a different MDC, changing its base DRG even when the diagnosis-procedure combination is unchanged. Cohort definitions in multi-year studies should be built from ICD-10 code lists, then checked against the grouper output for the relevant fiscal years.
Data-source operational depth
In Medicare FFS Part A (the native source), the DRG appears in the claim-level field `clm_drg_cd` (or equivalent in research files). The final DRG is present only on discharge claims (bill type 01X2 or 01X7-final; exclude 01X1 admit-through and 01X7-interim). Relative weights are in the annual IPPS final rule addenda (Tables 5 and 6). For cost proxies, multiply `clm_drg_cd` relative weight by the applicable hospital wage-index-adjusted base rate from CMS's impact file; for a research approximation, using the national standardized amount times the weight is acceptable with caveat. Link to MedPAR for a more efficient DRG-keyed inpatient extract. In commercial claims, MS-DRG equivalents may appear under different field names or may be imputed by the data vendor using the CMS grouper applied to ICD-10 codes. Verify with the data dictionary whether the DRG was assigned by the CMS free grouper or a proprietary engine; the answer affects replicability. In HCUP NIS and SID, MS-DRG and APR-DRG are both provided for Medicare discharges; APR-DRG SOI/ROM covers all payers. The APR-DRG is the 3M licensed product; treat it as a black-box-derived covariate. In Medicare Advantage encounter data (Part C), DRGs may be imputed or absent — see the MA pitfall note above.
Worked example
Scenario
A researcher wants to illustrate how the same principal diagnosis — heart failure (ICD-10-CM I50.9, unspecified) — routes three different patients to three different payment tiers based solely on their secondary diagnoses. Patient A has an MCC (acute kidney failure, N17.9, POA=Y). Patient B has only a CC (hypertensive heart disease, I11.9, POA=Y). Patient C has no qualifying secondary diagnosis. The hospital's DRG base rate is $7,000. The researcher needs to show the DRG assignment, relative weight, and estimated payment for each patient.
Dataset
Three heart failure admissions — same principal diagnosis, three severity tiers.
| patient_id | principal_dx | secondary_dx | POA_flag | assigned_DRG | DRG_description | relative_weight | base_rate_usd | estimated_payment_usd |
|---|---|---|---|---|---|---|---|---|
| A | I50.9 (heart failure, unspecified) | N17.9 (acute kidney failure) — qualifies as MCC | Y | 291 | Heart failure and shock with MCC | 2.21 | 7000 | 15470 |
| B | I50.9 (heart failure, unspecified) | I11.9 (hypertensive heart disease) — qualifies as CC | Y | 292 | Heart failure and shock with CC | 1.44 | 7000 | 10080 |
| C | I50.9 (heart failure, unspecified) | None qualifying | N/A | 293 | Heart failure and shock without CC/MCC | 1.06 | 7000 | 7420 |
Steps
The grouper reads each claim's principal diagnosis. All three patients have I50.9 (heart failure), so all three enter the heart failure base-DRG family within MDC 5 (Circulatory System), medical partition.
The grouper checks secondary diagnoses against the MCC list first. Patient A's secondary diagnosis N17.9 (acute kidney failure) appears on the CMS MCC list and carries POA=Y (it was present at admission), so the stay is assigned DRG 291 — the with-MCC tier.
Patient B's secondary diagnosis I11.9 (hypertensive heart disease) does not appear on the MCC list but does appear on the CC list with POA=Y, so the stay routes to DRG 292 — the with-CC tier.
Patient C has no secondary diagnoses that qualify as CC or MCC, so the stay routes to DRG 293 — the without-CC/MCC tier, the lowest-payment tier of the family.
Estimated payment is computed as relative_weight x base_rate: Patient A: 2.21 x 7000 = 15470. Patient B: 1.44 x 7000 = 10080. Patient C: 1.06 x 7000 = 7420.
The payment spread across the three tiers is 15470 / 7420 = 2.09 — more than double from the lowest to the highest tier for the identical principal diagnosis, driven entirely by the secondary diagnoses and their POA flags.
Result
Three patients admitted with the same heart failure diagnosis (I50.9) route to DRGs 291, 292, and 293 based on secondary diagnosis severity. Estimated payments are 2.21 x 7000 = 15470, 1.44 x 7000 = 10080, and 1.06 x 7000 = 7420 respectively. The highest tier (DRG 291 with MCC) pays approximately 15470 / 7420 = 2.09 times more than the lowest tier (DRG 293), even though the principal clinical condition is identical across all three admissions.
Severity Table
DRG 291
With MCC (e.g., acute kidney failure)
2.21
$15,470
DRG 292
With CC (e.g., hypertensive heart disease)
1.44
$10,080
DRG 293
Without CC/MCC
1.06
$7,420
Runnable example
python implementation
Collapse MS-DRG triplets to base DRGs and severity tiers, flag surgical vs. medical partition, and compute a DRG relative-weight cost proxy from a CMS weight lookup table. Demonstrates the core operations an analyst performs when building an inpatient...
import csv
from pathlib import Path
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class DRGRecord:
"""One row from the CMS IPPS Table 5 / relative-weight addendum."""
ms_drg: int
mdc: str # e.g., "05" for Circulatory System
partition: str # "M" = medical, "S" = surgical, "P" = pre-MDC
description: str
relative_weight: float
# Severity tier derived from the DRG number within its base-DRG family
severity_tier: str # "MCC", "CC", "none", or "N/A" (ungrouped / single-tier)
base_drg: int # all three tiers share the same base; e.g. 291->291, 292->291, 293->291
def load_drg_weights(csv_path: str) -> dict[int, DRGRecord]:
"""
Load the CMS annual DRG weight table. The CSV must have columns:
ms_drg, mdc, partition, description, relative_weight, severity_tier, base_drg
CMS publishes Table 5 of the IPPS final rule; this function expects a
pre-processed flat file derived from that table.
"""
table: dict[int, DRGRecord] = {}
with open(csv_path, newline="", encoding="utf-8") as f:
for row in csv.DictReader(f):
drg = int(row["ms_drg"])
table[drg] = DRGRecord(
ms_drg=drg,
mdc=row["mdc"].strip(),
partition=row["partition"].strip().upper(),
description=row["description"].strip(),
relative_weight=float(row["relative_weight"]),
severity_tier=row["severity_tier"].strip(),
base_drg=int(row["base_drg"]),
)
return table
def compute_drg_cost_proxy(
ms_drg: int,
drg_table: dict[int, DRGRecord],
base_rate_usd: float = 6940.0, # FY 2025 national standardized operating amount (approx)
) -> Optional[float]:
"""
Return weight × base_rate as a standardized inpatient cost proxy.
Returns None if the DRG is not found in the table (e.g., ungroupable DRG 999).
This is a first-order approximation; outlier top-ups, wage-index adjustments,
DSH, and IME add-ons are excluded.
"""
rec = drg_table.get(ms_drg)
if rec is None:
return None
return round(rec.relative_weight * base_rate_usd, 2)
# ---------------------------------------------------------------------------
# Example: process a list of inpatient discharge records
# ---------------------------------------------------------------------------
def classify_discharges(
discharges: list[dict], # each dict has at least "person_id", "discharge_date", "ms_drg"
drg_table: dict[int, DRGRecord],
base_rate_usd: float = 6940.0,
) -> list[dict]:
"""
Enrich each discharge record with:
- base_drg : severity-agnostic DRG (collapse triplet)
- severity_tier : MCC / CC / none
- partition : M (medical) or S (surgical)
- mdc : Major Diagnostic Category
- cost_proxy_usd : weight × base rate (None for ungroupable DRGs)
- is_surgical : boolean convenience flag
"""
results = []
for d in discharges:
drg_int = int(d.get("ms_drg", 0))
rec = drg_table.get(drg_int)
enriched = dict(d)
if rec:
enriched["base_drg"] = rec.base_drg
enriched["severity_tier"] = rec.severity_tier
enriched["partition"] = rec.partition
enriched["mdc"] = rec.mdc
enriched["is_surgical"] = rec.partition == "S"
enriched["cost_proxy_usd"] = round(rec.relative_weight * base_rate_usd, 2)
else:
# DRG 999 = ungroupable; exclude from clinical cohorts
enriched["base_drg"] = None
enriched["severity_tier"] = "ungroupable"
enriched["partition"] = None
enriched["mdc"] = None
enriched["is_surgical"] = False
enriched["cost_proxy_usd"] = None
results.append(enriched)
return results
# ---------------------------------------------------------------------------
# Demonstration with the heart failure triplet (FY 2025 approximate weights)
# ---------------------------------------------------------------------------
if __name__ == "__main__":
# Minimal inline DRG table for demonstration
demo_table = {
291: DRGRecord(291, "05", "M", "Heart failure and shock w MCC", 2.21, "MCC", 291),
292: DRGRecord(292, "05", "M", "Heart failure and shock w CC", 1.44, "CC", 291),
293: DRGRecord(293, "05", "M", "Heart failure and shock w/o CC/MCC", 1.06, "none", 291),
}
discharges = [
{"person_id": "A", "discharge_date": "2025-03-01", "ms_drg": 291},
{"person_id": "B", "discharge_date": "2025-03-05", "ms_drg": 292},
{"person_id": "C", "discharge_date": "2025-03-10", "ms_drg": 293},
]
BASE_RATE = 7000.0 # simplified for illustration
results = classify_discharges(discharges, demo_table, base_rate_usd=BASE_RATE)
print(f"{'ID':4} {'DRG':5} {'Base':5} {'Tier':5} {'Part':5} {'Cost':>10}")
for r in results:
print(f"{r['person_id']:4} {r['ms_drg']:5} {r['base_drg']:5} "
f"{r['severity_tier']:5} {r['partition']:5} "
f"${r['cost_proxy_usd']:>9,.2f}")
# Expected output (BASE_RATE = 7000):
# A 291 291 MCC M $15,470.00
# B 292 291 CC M $10,080.00
# C 293 291 none M $7,420.00r implementation
R implementation that reads a CMS DRG weight table and enriches inpatient discharge records with base DRG, severity tier, surgical/medical partition, MDC, and DRG relative-weight cost proxy. Uses only base R (no external packages required) for maximum...
# MS-DRG classification utilities — base R, no package dependencies
# Mirrors the Python classify_discharges() logic for cross-language consistency.
#' Load CMS IPPS DRG weight table from a flat CSV
#'
#' The CSV must contain columns:
#' ms_drg, mdc, partition, description, relative_weight, severity_tier, base_drg
#' Derived from CMS annual IPPS final rule Table 5 (downloadable from cms.gov).
#'
#' @param csv_path Path to the pre-processed weight CSV file
#' @return data.frame with one row per MS-DRG
load_drg_weights <- function(csv_path) {
drg_table <- read.csv(csv_path, stringsAsFactors = FALSE, strip.white = TRUE)
drg_table$ms_drg <- as.integer(drg_table$ms_drg)
drg_table$base_drg <- as.integer(drg_table$base_drg)
drg_table$relative_weight <- as.numeric(drg_table$relative_weight)
drg_table$partition <- toupper(drg_table$partition)
drg_table
}
#' Enrich discharge records with DRG classification fields and cost proxy
#'
#' @param discharges data.frame with at least columns: person_id, discharge_date, ms_drg
#' @param drg_table data.frame returned by load_drg_weights()
#' @param base_rate Numeric. National standardized operating base rate (USD).
#' Approx $6,940 for FY 2025; use $7,000 for illustration.
#' @return Original discharges data.frame with added columns:
#' base_drg, severity_tier, partition, mdc, is_surgical, cost_proxy_usd
classify_discharges <- function(discharges, drg_table, base_rate = 6940) {
result <- merge(
discharges,
drg_table[, c("ms_drg", "mdc", "partition", "description",
"relative_weight", "severity_tier", "base_drg")],
by = "ms_drg",
all.x = TRUE # keep unmatched rows (ungroupable DRGs)
)
# Flag ungroupable (DRG 999 or no match in weight table)
result$severity_tier[is.na(result$severity_tier)] <- "ungroupable"
result$cost_proxy_usd <- ifelse(
is.na(result$relative_weight),
NA_real_,
round(result$relative_weight * base_rate, 2)
)
result$is_surgical <- !is.na(result$partition) & result$partition == "S"
result
}
# ---------------------------------------------------------------------------
# Demonstration: heart failure severity triplet (FY 2025 approximate weights)
# ---------------------------------------------------------------------------
# Minimal inline DRG table for the heart failure family
demo_drg_table <- data.frame(
ms_drg = c(291L, 292L, 293L),
mdc = c("05", "05", "05"),
partition = c("M", "M", "M"),
description = c("HF w MCC", "HF w CC", "HF w/o CC/MCC"),
relative_weight = c(2.21, 1.44, 1.06),
severity_tier = c("MCC", "CC", "none"),
base_drg = c(291L, 291L, 291L),
stringsAsFactors = FALSE
)
demo_discharges <- data.frame(
person_id = c("A", "B", "C"),
discharge_date = as.Date(c("2025-03-01", "2025-03-05", "2025-03-10")),
ms_drg = c(291L, 292L, 293L),
stringsAsFactors = FALSE
)
BASE_RATE <- 7000 # simplified for illustration
result <- classify_discharges(demo_discharges, demo_drg_table, base_rate = BASE_RATE)
cat(sprintf(
"%-4s %-5s %-5s %-5s %-5s %12s\n",
"ID", "DRG", "Base", "Tier", "Part", "Cost_USD"
))
for (i in seq_len(nrow(result))) {
r <- result[i, ]
cat(sprintf(
"%-4s %-5d %-5d %-5s %-5s %12.2f\n",
r$person_id, r$ms_drg, r$base_drg,
r$severity_tier, r$partition, r$cost_proxy_usd
))
}
# Expected output (BASE_RATE = 7000):
# ID DRG Base Tier Part Cost_USD
# A 291 291 MCC M 15470.00
# B 292 291 CC M 10080.00
# C 293 291 none M 7420.00
# ---------------------------------------------------------------------------
# Tip: for severity-agnostic cohort definition, filter on base_drg
# ---------------------------------------------------------------------------
# hf_any <- result[result$base_drg == 291, ] # all heart failure, any severity
# hf_mcc <- result[result$severity_tier == "MCC", ] # MCC tier only