← Methods repository
concept

All-Cause vs Attributable Costs

The choice between summing every cost a patient incurs (all-cause) versus isolating only the costs caused by or assignable to a specific disease, treatment, or event (attributable), where attribution is operationalized by diagnosis coding, validated algorithms, episode windows, or an incremental comparison against a matched or modeled counterfactual.

Health_Economichealth_economiccost-of-illnessattributable-costsincremental-costsall-cause-costsclaims-cost-estimationtwo-part-modelplace-of-service
Methods reference only. Use primary source citations and local policy before applying this in a study protocol, regulatory submission, payer dossier, or clinical decision.

In plain language

When researchers add up what a patient cost the insurance system, they face a choice: count every single dollar spent on that person (all-cause costs), or count only the dollars that are directly tied to one specific disease (disease-attributable costs). All-cause costs give a full picture of the patient's total expense, while attributable costs try to isolate how much the disease itself is responsible for. The cleanest way to find the attributable share is to compare what patients with the disease spent against what a similar group without the disease spent, so that only the difference is credited to the condition.

All-cause

and attributable costs answer two different economic questions about the same patients, and conflating them is one of the most common and most consequential errors in claims- and EHR-based HEOR. All-cause cost is the sum of the paid or allowed amount on every claim — medical and pharmacy, related or unrelated — accruing during a patient's observation window. It measures the total economic footprint of the patient (the payer's total cost of care) and is the right numerator for budget impact, total-cost-of-care contracts, and any question where spillover onto comorbidity, complications, or downstream utilization is part of the value story. Attributable cost is the subset of spend caused by, or assignable to, the index condition or intervention. It is the numerator for cost-of-illness, disease burden, and the cost side of a cost-effectiveness or budget-impact model that prices a specific disease.

Core conceptual distinction — six operational definitions, not two

"Attributable" is not a single thing. Onukwugha et al. (2016) classify the field into six estimation methods, and the choice is an estimand decision that must be pre-specified before any programming: (1) Sum_All Medical — all-cause; sum everything. (2) Sum_Diagnosis-Specific — keep only claims carrying a qualifying diagnosis/procedure/NDC (the "direct disease-specific" or "top-down" sum). This is a descriptive accounting quantity: it answers "what was spent on claims labelled with this disease," not "what did the disease cause." (3) Matched — mean cost in the diseased/exposed cohort minus mean cost in a demographically and clinically matched non-diseased/unexposed cohort. The difference is the excess (incremental) cost. (4) Regression — model total cost on a disease indicator plus covariates (typically a two-part model, or a gamma/Tweedie GLM with log link); the coefficient on the indicator is the adjusted incremental cost. (5)/(6) Other_Total and Other_Incremental — phase-of-care, prevalence-weighted, or econometric variants. The critical fault line: methods (1)-(2) are bookkeeping (which dollars carry the right label), while (3)-(4) are causal/counterfactual (how much higher is spend because of the disease). Only the matched/regression incremental constructs estimate "the cost the disease caused," and only they are defensible as the cost-of-illness or the cost arm of a comparative economic model.

Pros, cons, and trade-offs (named alternatives)

- Sum_Diagnosis-Specific (attributable accounting) vs Sum_All Medical (all-cause): Diagnosis- specific focuses the signal and is trivial to compute from line-level claims, but it systematically under-counts (a disease-driven sepsis admission coded only with the sepsis code is dropped from a diabetes attributable sum) and mis-attributes (a routine PCP visit that happens to carry the disease code in any position is counted). The fraction of all-cause cost it captures — the "% attributable" — is often only 30-60% in chronic disease and should always be reported as a transparency metric. Prefer all-cause for total-cost-of-care and budget questions; prefer diagnosis-specific only for descriptive disease-spend accounting where you explicitly disclaim a causal reading. - Matched/incremental vs diagnosis-specific: The incremental approach is the only one that isolates caused cost and the only one that captures disease-driven spend that is coded under a different diagnosis (the str, MI, or fall that the disease produced). Cost: it requires a credible counterfactual, inherits every confounding and positivity problem of any comparative RWE analysis, and is sensitive to the matching/weighting specification and to the cost metric (allowed vs paid). Prefer incremental whenever the claim is "burden caused by the disease" or "cost offset of the treatment." - Matching vs regression for the incremental estimand: Matching is transparent and makes the comparison explicit but discards unmatched patients and loses power; a two-part or gamma-GLM regression uses the full sample and handles the cost distribution (mass at zero, right skew) directly but rests on functional-form assumptions. Report both when feasible; they should agree. - vs HCRU (resource-utilization counts): Costs add the monetary and intensity weighting that raw counts lack and map directly onto budget and HTA decisions, but dollar attribution is more consequential and more scrutinized than count attribution, and costs move with price and payment- model changes that volume does not. Apply the same attribution rule to HCRU and costs and report both — see `hcru-healthcare-resource-utilization`.

When to use

Use all-cause for payer total-cost-of-care, budget impact, value-based-contract performance, and any intervention with plausible spillover (e.g., a drug that reduces all-cause hospitalization). Use attributable/incremental for cost-of-illness, disease burden, the cost arm of a CEA/CUA, and any "cost offset of treating X" message — and within attributable, use the matched or regression incremental construct, not the diagnosis-specific sum, whenever the claim is causal.

When NOT to use / when this is actively misleading

- Do not report a diagnosis-specific sum as "the cost of the disease." It is descriptive accounting; presenting it as caused cost overstates precision and is the single most common COI error. If a reviewer asks "compared to what?", a diagnosis-specific sum has no answer — that is the tell that you needed an incremental design. - Do not use all-cause incremental as a disease-cost estimate when arms differ on unrelated spend. If the exposed cohort is older/sicker, all-cause incremental folds unrelated comorbidity cost into the estimate; this is the mirror failure of the diagnosis-specific under-count. - Incremental costs with a non-overlapping comparator are uninterpretable. If the disease/exposure is reserved for sicker patients, positivity fails, matching discards most of the cohort, and the surviving estimand no longer maps to a meaningful population — the same positivity logic as in `active-comparator-new-user`. - Beware circularity: using the same code list to define the cohort and to attribute its costs guarantees a high apparent attributable fraction by construction. Define attribution independently and report sensitivity to the code list. - Differential follow-up and competing risks break naive cost sums. In elderly claims, the sicker arm dies sooner and therefore accrues less cumulative cost — a survivor will out-spend a decedent — so unadjusted mean cumulative cost can run backwards to the disease effect. Use cost over a fixed window (e.g., PPPM over observed person-time), or phase-of-care / partitioned-survival costing that handles the truncation, rather than total cost to death.

Data-source operational depth

- Claims (FFS): The reference substrate for cost attribution because every adjudicated line carries a paid/allowed amount, a service date, place of service, and diagnosis/procedure/NDC fields needed for both labelling and summing. Failure modes: (a) Medicare Advantage / capitated person-time has no FFS claim-level dollars — MA encounter records frequently lack reliable paid amounts, so MA person-time silently deflates both all-cause and attributable sums; restrict to FFS (or commercial with full pharmacy benefit) and exclude MA-only spans. (b) Adjudication lag and claim reversals — pull with a run-out window (commonly 3-6 months) and net out reversed/voided lines before summing, or late and negative claims distort totals. (c) Bundled/episode payments — a single bundle payment may be the only true dollar figure while internal service lines show utilization but not granular cost; treat the bundle as the attributable cost and use internal lines only for HCRU. (d) Diagnosis position — primary-only is conservative and misses secondary manifestations; any- position over-attributes (rule-out, history, and comorbidity codes). (e) Medical/pharmacy crossover — infused drugs bill to the medical benefit as J-codes (HCPCS), not pharmacy NDCs; a pharmacy-only attribution rule will miss them entirely. - EHR: Has charges, not adjudicated payer cost, and only for care delivered inside the system. External care — the main source of "unrelated" all-cause cost — is invisible, so all-cause sums are structurally incomplete and attribution to a counterfactual is unreliable without linkage to claims. Charge-to-cost ratios or reference unit costs are required to monetize, and encounter-driven capture means a patient who leaves the system is differentially lost. - Registry: Strong for clean disease confirmation and severity (sharpening the labelling side of attribution) but rarely carries cost; link to claims for the dollar figures and for the full all- cause footprint. - Linked claims-EHR(-registry): The ideal substrate — EHR/registry severity for credible matching plus claims completeness for the dollars — but linkage introduces selection (only the linkable subset) and date-discrepancy issues that must be reconciled before windowing costs.

Standardization

Both all-cause and attributable totals are almost always converted to PPPM/PPPY using person-time denominators, and the same person-time and enrollment rules must apply to the numerator costs and to any comparator (see `healthcare-costs-pppm-pppy-pmpm`). Pre-specify the cost basis (allowed vs paid), the perspective (payer vs patient out-of-pocket vs both), and any inflation-adjustment to a common dollar year.

Worked claims example

Question: what is the diabetes-attributable annual medical + pharmacy cost in a commercial + Medicare FFS database? (1) Cohort: adults with >=2 outpatient or >=1 inpatient diabetes diagnosis (ICD-10 E11.x) and >=365 days of continuous medical + pharmacy FFS enrollment (exclude MA-only spans); index_date = first qualifying diagnosis. (2) Follow-up window: the 365 days from index_date, censoring at disenrollment, death, or data end; require full enrollment in the window or annualize over observed person-months. (3) All-cause cost: sum `paid_amt` over all medical and pharmacy claims with `service_date` in the window. (4) Diagnosis-specific attributable cost: sum `paid_amt` only on medical claims carrying E11.x in any diagnosis position, plus pharmacy claims whose NDC maps to an antidiabetic drug class — and report the attributable fraction (attributable / all-cause), which will land well under 100% and is itself a finding. (5) Incremental (excess) cost: draw a non-diabetic comparator from the same database with identical enrollment rules, 1:1 match on age band, sex, region, index calendar quarter, and a comorbidity score measured in the 365-day baseline, then take mean(all-cause cost | diabetic) - mean(all-cause cost | matched non-diabetic) — this is the defensible "cost caused by diabetes," and it will typically exceed the diagnosis-specific sum because it recaptures the disease-driven spend coded under MI, renal, and amputation claims. (6) Robustness: repeat the incremental estimate with a two-part / gamma-GLM regression on the unmatched sample, vary diagnosis position (primary-only vs any), and report PPPM so the estimate is comparable across patients with partial follow-up.

Interpreting the output

A researcher reports three cost figures for three diabetic patients versus matched non-diabetic controls: all-cause mean cost $19,600 per diabetic patient, diagnosis-specific (diabetes-labelled) mean $7,467 (attributable fraction 38%), and matched-control incremental cost $9,733.

(1) Formal interpretation. The all-cause figure ($19,600) is the total annual allowed cost per diabetic patient regardless of which condition prompted each claim; it is a payer total-cost-of-care estimate, not an estimate of what diabetes caused. The diagnosis-specific figure ($7,467) is the accounting sum of claims carrying a diabetes label and represents only 38% of all-cause cost — 62% of spending is on claims coded for other diagnoses, some of which were caused by diabetes but labelled under downstream complications or comorbidities. It is a descriptive accounting construct, not a causal estimate. The incremental figure ($9,733) subtracts the matched non-diabetic mean from the diabetic mean, attributing the difference to diabetes; it exceeds the diagnosis-specific sum because it recaptures disease-driven spend labelled under other codes. The incremental estimate rests on the assumption that matched controls are a credible counterfactual — it inherits all the confounding and positivity considerations of any comparative design.

(2) Practical interpretation. When a dossier claims "diabetes costs $X per patient," ask which method produced X. A diagnosis-specific $7,467 framing systematically understates burden; the matched incremental $9,733 is the defensible figure for cost-of-illness, value arguments, and cost-offset modeling. Report all three for transparency; lead with incremental as the primary estimate.

Worked example

Scenario

A researcher studying type 2 diabetes wants to know both how much diabetic patients cost in total and how much of that cost is caused by diabetes. She identifies three diabetic patients and three matched non-diabetic patients with similar age, sex, and general health. Over one year she adds up each person's claims. She then computes all-cause costs (every dollar), diagnosis-specific attributable costs (only claims labelled with a diabetes code or antidiabetic prescription), and the incremental attributable cost (the average difference between diabetic and matched non-diabetic patients).

Dataset

Annual claims summary for three diabetic patients and their matched non-diabetic controls. All-cause = every claim; diabetes-labelled = only claims with a diabetes diagnosis code or antidiabetic drug.

person_idgroupmatch_idall_cause_cost_usddiabetes_labelled_cost_usd
2001diabetic1184007200
2002diabetic2246009100
2003diabetic3158006100
3001non-diabetic19800
3002non-diabetic211200
3003non-diabetic38600

Steps

  • Average all-cause cost for diabetic patients: (18,400 + 24,600 + 15,800) / 3 = 58,800 / 3 = 19,600 dollars.

  • Average all-cause cost for matched non-diabetic patients: (9,800 + 11,200 + 8,600) / 3 = 29,600 / 3 = 9,867 dollars (rounded to the nearest dollar).

  • Incremental (caused) cost = diabetic average minus non-diabetic average: 19,600 - 9,867 = 9,733 dollars per patient per year. This is the best estimate of what diabetes itself cost, because it cancels out spending that any similar patient would have had regardless of diabetes.

  • Average diagnosis-specific attributable cost (diabetes-labelled claims only): (7,200 + 9,100 + 6,100) / 3 = 22,400 / 3 = 7,467 dollars.

  • Attributable fraction using the diagnosis-specific method: 7,467 / 19,600 = 0.38, meaning only 38 percent of total diabetic spending carries a diabetes label. The other 62 percent of spending is on claims coded for complications, other conditions, or unrelated care, but some of that spending was still caused by diabetes.

  • Notice that the diagnosis-specific sum (7,467 dollars) is lower than the incremental estimate (9,733 dollars). The difference exists because some diabetes-driven spending, such as a heart-disease hospitalization caused by diabetes, is coded under the heart-disease diagnosis and would be missed by the label-only rule.

Result

All-cause cost per diabetic patient: 19,600 dollars. Diagnosis-specific attributable cost: 7,467 dollars (attributable fraction = 38%). Incremental (caused) cost versus matched controls: 9,733 dollars. The incremental figure is the more defensible estimate of what diabetes costs the system because it recovers disease-driven spending that is labelled under other diagnosis codes.

Runnable example

python implementation

All-cause vs attributable cost from claims, plus the matched-incremental (excess) cost. Required inputs (already cleaned, de-duplicated, reversals netted out): claims : person_id, service_date (datetime), paid_amt (float), benefit in {'MED','RX'}, dx1..dxN...

import pandas as pd
import numpy as np

WINDOW_DAYS = 365
DM_DX_PREFIX = "E11"          # type 2 diabetes, ICD-10
DM_RX_CLASS = "ANTIDIABETIC" # value of ndc_drug_class for antidiabetic fills

def cost_summary(claims: pd.DataFrame, cohort: pd.DataFrame) -> pd.DataFrame:
    dx_cols = [c for c in claims.columns if c.startswith("dx")]

    c = claims.merge(cohort[["person_id", "index_date"]], on="person_id")
    # Keep only claims inside the fixed post-index window (avoids competing-risk truncation).
    in_window = ((c["service_date"] >= c["index_date"]) &
                 (c["service_date"] <  c["index_date"] + pd.Timedelta(days=WINDOW_DAYS)))
    c = c.loc[in_window].copy()

    # Diagnosis-specific attribution: E11.x in ANY dx position, OR an antidiabetic NDC class.
    dx_hit = c[dx_cols].apply(lambda s: s.astype("string").str.startswith(DM_DX_PREFIX, na=False)).any(axis=1)
    rx_hit = (c["benefit"] == "RX") & (c["ndc_drug_class"] == DM_RX_CLASS)
    c["attributable"] = dx_hit | rx_hit

    per_person = c.groupby("person_id").agg(
        all_cause=("paid_amt", "sum"),
        attributable=("paid_amt", lambda s: s[c.loc[s.index, "attributable"]].sum()),
    ).reset_index()
    return cohort.merge(per_person, on="person_id", how="left").fillna({"all_cause": 0.0,
                                                                        "attributable": 0.0})

def attributable_fraction(summary: pd.DataFrame) -> float:
    # Transparency metric: share of all-cause spend captured by the diagnosis-specific rule.
    return summary["attributable"].sum() / summary["all_cause"].sum()

def matched_incremental_cost(summary: pd.DataFrame) -> float:
    # Excess (caused) cost = mean ALL-CAUSE among diabetics minus their matched non-diabetic controls.
    paired = summary.dropna(subset=["match_id"])
    wide = paired.pivot_table(index="match_id", columns="diabetic",
                              values="all_cause", aggfunc="mean")
    wide.columns = ["non_diabetic", "diabetic"]            # False, True after pivot ordering
    return float((wide["diabetic"] - wide["non_diabetic"]).mean())
r implementation

All-cause vs attributable (diagnosis-specific) cost and matched-incremental cost with data.table. Inputs mirror the Python version: claims : person_id, service_date (Date), paid_amt, benefit ('MED'/'RX'), dx1..dxN (character, ICD-10), ndc_drug_class...

library(data.table)
WINDOW_DAYS  <- 365L
DM_DX_PREFIX <- "E11"
DM_RX_CLASS  <- "ANTIDIABETIC"

cost_summary <- function(claims, cohort) {
  setDT(claims); setDT(cohort)
  dx_cols <- grep("^dx", names(claims), value = TRUE)

  c <- merge(claims, cohort[, .(person_id, index_date)], by = "person_id")
  c <- c[service_date >= index_date &
         service_date <  index_date + WINDOW_DAYS]

  # Diagnosis-specific attribution: E11.x in any dx position, or an antidiabetic NDC class.
  dx_hit <- Reduce(`|`, lapply(dx_cols, function(col)
              startsWith(as.character(c[[col]]), DM_DX_PREFIX) %in% TRUE))
  rx_hit <- c$benefit == "RX" & c$ndc_drug_class == DM_RX_CLASS & !is.na(c$ndc_drug_class)
  c[, attributable := dx_hit | rx_hit]

  per_person <- c[, .(all_cause    = sum(paid_amt),
                      attributable = sum(paid_amt[attributable])), by = person_id]
  out <- merge(cohort, per_person, by = "person_id", all.x = TRUE)
  out[is.na(all_cause),    all_cause    := 0]
  out[is.na(attributable), attributable := 0]
  out[]
}

attributable_fraction <- function(summary) sum(summary$attributable) / sum(summary$all_cause)

matched_incremental_cost <- function(summary) {
  paired <- summary[!is.na(match_id)]
  w <- dcast(paired, match_id ~ diabetic, value.var = "all_cause", fun.aggregate = mean)
  mean(w[["TRUE"]] - w[["FALSE"]], na.rm = TRUE)   # excess (caused) cost per matched pair
}