The ANOVA lesson in this chapter found a real, statistically significant difference between lines. This lesson uses the same 3-line dataset's time-to-failure records and finds the opposite: a descriptive difference in median survival that does not clear the log-rank test's significance bar. Both outcomes are real lmda computations on real data — a "not significant" result is not a failed lesson, it's the correct honest answer for this sample.

The real dataset

data/time_to_failure.csv records one row per machine (25 machines per line, 75 rows total): a line, a time-to-failure or time-to-censoring in days, and an event flag (1 = failed and observed, 0 = still running when the 180-day observation window ended — right-censored, not "survived forever"). | line | machine | time | event | |---|---|---|---| | A | 1 | 180.0 | 0 | | A | 2 | 138.95 | 1 | | A | 3 | 73.93 | 1 | | B | 1 | 6.37 | 1 | | C | 1 | 1.23 | 1 | Censored rows (event=0) still carry information — "this machine ran for at least time days" — which is exactly what Kaplan-Meier is built to use without discarding or mis-treating them as failures.

Kaplan-Meier survival curves per line

lmda kaplanmeier data/time_to_failure.csv --time time --event event --group line --format json
{
  "censored": 26,
  "confidence": 0.95,
  "curves": [
    {
      "censored": 6,
      "events": 19,
      "group": "A",
      "median_survival": 127.67,
      "n": 25,
      "points": [
        {
          "at_risk": 25,
          "censored": 0,
          "ci_lower": 0.883185413178315,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.03919183588453085,
          "survival": 0.96,
          "time": 19.87
        },
        {
          "at_risk": 24,
          "censored": 0,
          "ci_lower": 0.8136550200144667,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.054258639865002144,
          "survival": 0.92,
          "time": 34.72
        },
        {
          "at_risk": 23,
          "censored": 0,
          "ci_lower": 0.7526174185431462,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.06499230723708768,
          "survival": 0.88,
          "time": 35.02
        },
        {
          "at_risk": 22,
          "censored": 0,
          "ci_lower": 0.6962930669033272,
          "ci_upper": 0.9837069330966728,
          "events": 1,
          "standard_error": 0.07332121111929343,
          "survival": 0.84,
          "time": 44.63
        },
        {
          "at_risk": 21,
          "censored": 0,
          "ci_lower": 0.6432028812367957,
          "ci_upper": 0.9567971187632044,
          "events": 1,
          "standard_error": 0.08000000000000002,
          "survival": 0.8,
          "time": 56.3
        },
        {
          "at_risk": 20,
          "censored": 0,
          "ci_lower": 0.5925864893272221,
          "ci_upper": 0.9274135106727779,
          "events": 1,
          "standard_error": 0.08541662601625048,
          "survival": 0.76,
          "time": 73.93
        },
        {
          "at_risk": 19,
          "censored": 0,
          "ci_lower": 0.5439956707064356,
          "ci_upper": 0.8960043292935643,
          "events": 1,
          "standard_error": 0.0897997772825746,
          "survival": 0.72,
          "time": 75.19
        },
        {
          "at_risk": 18,
          "censored": 0,
          "ci_lower": 0.4971447086482821,
          "ci_upper": 0.862855291351718,
          "events": 1,
          "standard_error": 0.0932952303175248,
          "survival": 0.68,
          "time": 78.79
        },
        {
          "at_risk": 17,
          "censored": 0,
          "ci_lower": 0.45184345748415483,
          "ci_upper": 0.8281565425158453,
          "events": 1,
          "standard_error": 0.096,
          "survival": 0.64,
          "time": 89.0
        },
        {
          "at_risk": 16,
          "censored": 0,
          "ci_lower": 0.40796353294578763,
          "ci_upper": 0.7920364670542124,
          "events": 1,
          "standard_error": 0.09797958971132711,
          "survival": 0.6,
          "time": 93.46
        },
        {
          "at_risk": 15,
          "censored": 0,
          "ci_lower": 0.3654198927516965,
          "ci_upper": 0.7545801072483036,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.56,
          "time": 104.73
        },
        {
          "at_risk": 14,
          "censored": 0,
          "ci_lower": 0.3241604614338306,
          "ci_upper": 0.7158395385661694,
          "events": 1,
          "standard_error": 0.09991996797437439,
          "survival": 0.52,
          "time": 115.33
        },
        {
          "at_risk": 13,
          "censored": 0,
          "ci_lower": 0.2841604614338306,
          "ci_upper": 0.6758395385661693,
          "events": 1,
          "standard_error": 0.09991996797437437,
          "survival": 0.48,
          "time": 127.67
        },
        {
          "at_risk": 12,
          "censored": 0,
          "ci_lower": 0.24541989275169648,
          "ci_upper": 0.6345801072483035,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.44,
          "time": 138.95
        },
        {
          "at_risk": 11,
          "censored": 0,
          "ci_lower": 0.20796353294578765,
          "ci_upper": 0.5920364670542124,
          "events": 1,
          "standard_error": 0.09797958971132713,
          "survival": 0.4,
          "time": 149.86
        },
        {
          "at_risk": 10,
          "censored": 0,
          "ci_lower": 0.1718434574841548,
          "ci_upper": 0.5481565425158452,
          "events": 1,
          "standard_error": 0.096,
          "survival": 0.36,
          "time": 152.92
        },
        {
          "at_risk": 9,
          "censored": 0,
          "ci_lower": 0.13714470864828204,
          "ci_upper": 0.5028552913517179,
          "events": 1,
          "standard_error": 0.09329523031752482,
          "survival": 0.32,
          "time": 156.8
        },
        {
          "at_risk": 8,
          "censored": 0,
          "ci_lower": 0.1039956707064357,
          "ci_upper": 0.4560043292935644,
          "events": 1,
          "standard_error": 0.0897997772825746,
          "survival": 0.28,
          "time": 174.42
        },
        {
          "at_risk": 7,
          "censored": 0,
          "ci_lower": 0.07258648932722206,
          "ci_upper": 0.4074135106727779,
          "events": 1,
          "standard_error": 0.08541662601625048,
          "survival": 0.24,
          "time": 179.18
        },
        {
          "at_risk": 6,
          "censored": 6,
          "ci_lower": 0.07258648932722206,
          "ci_upper": 0.4074135106727779,
          "events": 0,
          "standard_error": 0.08541662601625048,
          "survival": 0.24,
          "time": 180.0
        }
      ]
    },
    {
      "censored": 9,
      "events": 16,
      "group": "B",
      "median_survival": 99.72,
      "n": 25,
      "points": [
        {
          "at_risk": 25,
          "censored": 0,
          "ci_lower": 0.883185413178315,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.03919183588453085,
          "survival": 0.96,
          "time": 6.37
        },
        {
          "at_risk": 24,
          "censored": 0,
          "ci_lower": 0.8136550200144667,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.054258639865002144,
          "survival": 0.92,
          "time": 17.91
        },
        {
          "at_risk": 23,
          "censored": 0,
          "ci_lower": 0.7526174185431462,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.06499230723708768,
          "survival": 0.88,
          "time": 19.62
        },
        {
          "at_risk": 22,
          "censored": 0,
          "ci_lower": 0.6962930669033272,
          "ci_upper": 0.9837069330966728,
          "events": 1,
          "standard_error": 0.07332121111929343,
          "survival": 0.84,
          "time": 22.5
        },
        {
          "at_risk": 21,
          "censored": 0,
          "ci_lower": 0.6432028812367957,
          "ci_upper": 0.9567971187632044,
          "events": 1,
          "standard_error": 0.08000000000000002,
          "survival": 0.8,
          "time": 35.77
        },
        {
          "at_risk": 20,
          "censored": 0,
          "ci_lower": 0.5925864893272221,
          "ci_upper": 0.9274135106727779,
          "events": 1,
          "standard_error": 0.08541662601625048,
          "survival": 0.76,
          "time": 37.04
        },
        {
          "at_risk": 19,
          "censored": 0,
          "ci_lower": 0.5439956707064356,
          "ci_upper": 0.8960043292935643,
          "events": 1,
          "standard_error": 0.0897997772825746,
          "survival": 0.72,
          "time": 56.75
        },
        {
          "at_risk": 18,
          "censored": 0,
          "ci_lower": 0.4971447086482821,
          "ci_upper": 0.862855291351718,
          "events": 1,
          "standard_error": 0.0932952303175248,
          "survival": 0.68,
          "time": 57.37
        },
        {
          "at_risk": 17,
          "censored": 0,
          "ci_lower": 0.45184345748415483,
          "ci_upper": 0.8281565425158453,
          "events": 1,
          "standard_error": 0.096,
          "survival": 0.64,
          "time": 60.53
        },
        {
          "at_risk": 16,
          "censored": 0,
          "ci_lower": 0.40796353294578763,
          "ci_upper": 0.7920364670542124,
          "events": 1,
          "standard_error": 0.09797958971132711,
          "survival": 0.6,
          "time": 64.88
        },
        {
          "at_risk": 15,
          "censored": 0,
          "ci_lower": 0.3654198927516965,
          "ci_upper": 0.7545801072483036,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.56,
          "time": 66.7
        },
        {
          "at_risk": 14,
          "censored": 0,
          "ci_lower": 0.3241604614338306,
          "ci_upper": 0.7158395385661694,
          "events": 1,
          "standard_error": 0.09991996797437439,
          "survival": 0.52,
          "time": 83.51
        },
        {
          "at_risk": 13,
          "censored": 0,
          "ci_lower": 0.2841604614338306,
          "ci_upper": 0.6758395385661693,
          "events": 1,
          "standard_error": 0.09991996797437437,
          "survival": 0.48,
          "time": 99.72
        },
        {
          "at_risk": 12,
          "censored": 0,
          "ci_lower": 0.24541989275169648,
          "ci_upper": 0.6345801072483035,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.44,
          "time": 107.89
        },
        {
          "at_risk": 11,
          "censored": 0,
          "ci_lower": 0.20796353294578765,
          "ci_upper": 0.5920364670542124,
          "events": 1,
          "standard_error": 0.09797958971132713,
          "survival": 0.4,
          "time": 162.8
        },
        {
          "at_risk": 10,
          "censored": 0,
          "ci_lower": 0.1718434574841548,
          "ci_upper": 0.5481565425158452,
          "events": 1,
          "standard_error": 0.096,
          "survival": 0.36,
          "time": 166.95
        },
        {
          "at_risk": 9,
          "censored": 9,
          "ci_lower": 0.1718434574841548,
          "ci_upper": 0.5481565425158452,
          "events": 0,
          "standard_error": 0.096,
          "survival": 0.36,
          "time": 180.0
        }
      ]
    },
    {
      "censored": 11,
      "events": 14,
      "group": "C",
      "median_survival": 172.72,
      "n": 25,
      "points": [
        {
          "at_risk": 25,
          "censored": 0,
          "ci_lower": 0.883185413178315,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.03919183588453085,
          "survival": 0.96,
          "time": 1.23
        },
        {
          "at_risk": 24,
          "censored": 0,
          "ci_lower": 0.8136550200144667,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.054258639865002144,
          "survival": 0.92,
          "time": 6.9
        },
        {
          "at_risk": 23,
          "censored": 0,
          "ci_lower": 0.7526174185431462,
          "ci_upper": 1.0,
          "events": 1,
          "standard_error": 0.06499230723708768,
          "survival": 0.88,
          "time": 12.4
        },
        {
          "at_risk": 22,
          "censored": 0,
          "ci_lower": 0.6962930669033272,
          "ci_upper": 0.9837069330966728,
          "events": 1,
          "standard_error": 0.07332121111929343,
          "survival": 0.84,
          "time": 24.59
        },
        {
          "at_risk": 21,
          "censored": 0,
          "ci_lower": 0.6432028812367957,
          "ci_upper": 0.9567971187632044,
          "events": 1,
          "standard_error": 0.08000000000000002,
          "survival": 0.8,
          "time": 29.52
        },
        {
          "at_risk": 20,
          "censored": 0,
          "ci_lower": 0.5925864893272221,
          "ci_upper": 0.9274135106727779,
          "events": 1,
          "standard_error": 0.08541662601625048,
          "survival": 0.76,
          "time": 29.66
        },
        {
          "at_risk": 19,
          "censored": 0,
          "ci_lower": 0.5439956707064356,
          "ci_upper": 0.8960043292935643,
          "events": 1,
          "standard_error": 0.0897997772825746,
          "survival": 0.72,
          "time": 35.3
        },
        {
          "at_risk": 18,
          "censored": 0,
          "ci_lower": 0.4971447086482821,
          "ci_upper": 0.862855291351718,
          "events": 1,
          "standard_error": 0.0932952303175248,
          "survival": 0.68,
          "time": 45.27
        },
        {
          "at_risk": 17,
          "censored": 0,
          "ci_lower": 0.45184345748415483,
          "ci_upper": 0.8281565425158453,
          "events": 1,
          "standard_error": 0.096,
          "survival": 0.64,
          "time": 121.92
        },
        {
          "at_risk": 16,
          "censored": 0,
          "ci_lower": 0.40796353294578763,
          "ci_upper": 0.7920364670542124,
          "events": 1,
          "standard_error": 0.09797958971132711,
          "survival": 0.6,
          "time": 135.22
        },
        {
          "at_risk": 15,
          "censored": 0,
          "ci_lower": 0.3654198927516965,
          "ci_upper": 0.7545801072483036,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.56,
          "time": 141.12
        },
        {
          "at_risk": 14,
          "censored": 0,
          "ci_lower": 0.3241604614338306,
          "ci_upper": 0.7158395385661694,
          "events": 1,
          "standard_error": 0.09991996797437439,
          "survival": 0.52,
          "time": 146.85
        },
        {
          "at_risk": 13,
          "censored": 0,
          "ci_lower": 0.2841604614338306,
          "ci_upper": 0.6758395385661693,
          "events": 1,
          "standard_error": 0.09991996797437437,
          "survival": 0.48,
          "time": 172.72
        },
        {
          "at_risk": 12,
          "censored": 0,
          "ci_lower": 0.24541989275169648,
          "ci_upper": 0.6345801072483035,
          "events": 1,
          "standard_error": 0.09927738916792686,
          "survival": 0.44,
          "time": 176.91
        },
        {
          "at_risk": 11,
          "censored": 11,
          "ci_lower": 0.24541989275169648,
          "ci_upper": 0.6345801072483035,
          "events": 0,
          "standard_error": 0.09927738916792686,
          "survival": 0.44,
          "time": 180.0
        }
      ]
    }
  ],
  "dropped": 0,
  "event": "event",
  "events": 49,
  "group": "line",
  "n": 75,
  "time": "time"
}

Each line's curve steps down at every observed failure time and holds flat across censored gaps. Reading median_survival per group: line A ≈ 127.7 days, line B ≈ 99.7 days, line C ≈ 172.7 days — line C's machines are lasting descriptively longest in this sample, line B shortest.

Is the difference real? The log-rank test

A descriptive gap between 3 median-survival numbers could still be sampling noise with only 25 machines per line. The log-rank test compares observed vs. expected failure counts per group across every event time to test whether the underlying survival curves are the same:

lmda logrank data/time_to_failure.csv --time time --event event --group line --format json
{
  "censored": 26,
  "chi_square": 1.0396746340021665,
  "degrees_of_freedom": 2,
  "dropped": 0,
  "event": "event",
  "events": 49,
  "group": "line",
  "groups": [
    {
      "expected_events": 16.500932890480293,
      "group": "A",
      "n": 25,
      "observed_events": 19
    },
    {
      "expected_events": 15.243313685455735,
      "group": "B",
      "n": 25,
      "observed_events": 16
    },
    {
      "expected_events": 17.25575342406397,
      "group": "C",
      "n": 25,
      "observed_events": 14
    }
  ],
  "n": 75,
  "p_value": 0.5946172742235007,
  "time": "time"
}

p_value is well above 0.05: at this sample size, the observed spread in median survival is not distinguishable from what 3 curves with the same underlying survival function could produce by chance.

Honesty

This is the real, computed result for this sample — not a rounding artifact and not a weaker version of the ANOVA finding. The descriptive numbers (median survival 127.7 / 99.7 / 172.7 days) are true statements about these 75 machines; the log-rank test says that with only 25 machines per line, that descriptive spread does not clear the bar for "the 3 lines have genuinely different failure-time distributions." Reporting only the descriptive medians and skipping the log-rank test would overstate the evidence — a real analysis has to say both halves. As with the ANOVA lesson, this dataset is a realistic simulated dataset (lmda's own case-study-1 worked example), not observed production data, so treat "line C's machines last longest" as a property of this sample, not a manufacturing claim.

Implementation notes

  • Right-censoring (event=0) is not the same as "no failure" — a censored machine contributes "at risk, no observed failure" information up to its censoring time and then leaves the risk set; Kaplan-Meier's step function only drops at observed events, not at censoring times.
  • Both commands above are re-run against the committed CSV on every validate_source.py pass and must byte-for-byte match the checked-in outputs/*.json.
  • Cross-reference: anova-defect-rate-by-line (this chapter) for a significant result on the same 3 lines' defect-rate data — the pairing is deliberate: real data does not always cross the significance line, and knowing which is which matters as much as running the test.