ds@mcpanalytics.aiEmail your data and your question and get an answer about your own data, with the method shown.Email your data and question. Get an answer.

Weibull Analysis: Practical Guide for Data-Driven Decisions

By MCP Analytics Team | Published , updated

Parts wear out. The question is when, and what to do about it. Weibull analysis turns a list of failure times into two numbers: a shape that says how the failure risk changes with age, and a scale that says how long units usually last. This guide fits a Weibull model to a famous public data set of 23 ball bearings, shows every step with code you can run, and then turns the result into a warranty number and a replacement age. Weibull can also use units that have not failed yet, so you do not have to wait for every part to break.

The Decision Framework: When Weibull Analysis Answers Your Question

Before diving into mathematics or software, determine whether Weibull analysis is the right tool. This decision framework maps business questions to analytical approaches.

To estimate how long until your own customers cancel, counting the ones who have not yet, try the free survival analysis tool.

Use Weibull Analysis When You Need To:

Predict warranty costs before they happen. Your product launches in 6 months. Finance needs warranty reserve estimates. Weibull analysis on prototype testing can project failure rates at 1-year, 2-year, and 3-year horizons, with wide ranges when few units have failed. This gives finance an estimate before real-world failures arrive.

Optimize maintenance schedules with data, not guesses. Current preventive maintenance at 1000 hours wastes money if failures cluster at 2000 hours, or misses problems if they occur at 600 hours. Weibull reveals the actual failure distribution, letting you schedule maintenance when it prevents failures rather than when calendars say so.

Identify whether failures are design problems or manufacturing defects. Early failures (shape parameter < 1) indicate quality control issues, parts that should never have shipped. Late failures (shape parameter > 1) indicate wear-out and potential design limitations. This distinction determines whether you fix production processes or redesign components.

Compare reliability across suppliers, designs, or operating conditions. Which bearing manufacturer delivers better longevity? Does operating temperature affect failure rates? Weibull parameters allow a direct comparison. The characteristic life η is the time by which 63.2% of a group may fail, median life is the time by which 50% may fail, and the shape value β shows how the failure rate changes over time.

Use incomplete data instead of throwing it away. Suppose you started tracking 200 units 6 months ago and only 25 have failed. An analysis that drops the 175 units still running throws information away. Weibull incorporates censored data (units that have not failed yet), so the fit uses the full dataset.

Key Insight: The Shape Parameter Drives Decisions

Weibull analysis produces two key numbers: characteristic life (η) sets the time scale of failures, and shape parameter (β) shows how the failure rate changes with age. β < 1 means fix manufacturing quality. β ≈ 1 means failures are random (hard to prevent). β > 1 means implement preventive maintenance before wear-out. This parameter can point toward design changes, production process improvements, or maintenance programs, though it does not decide the choice alone. The estimate carries a range, so read it with its interval.

Skip Weibull Analysis When:

Failure rates are truly constant over time. If your failure pattern shows β ≈ 1 (constant hazard), use simpler exponential distribution models. Weibull reduces to exponential in this case, so the added complexity provides no benefit. Electronics without wear-out often fit this pattern.

You have multiple distinct failure modes mixing together. A motor that fails from bearing wear, electrical shorts, and corrosion creates a mixed distribution that violates Weibull assumptions. Either separate failures by mode and analyze each independently, or use competing risks methods that explicitly model multiple failure mechanisms.

You need to compare many variables simultaneously. Weibull handles one or two covariates (operating temperature, load level) reasonably well. For analyzing many factors at once (material grade, supplier, production line, installation date, geographic region, usage intensity) use accelerated failure time models or Cox regression instead. These methods handle multivariate analysis more efficiently.

Your data includes repairable systems with multiple failures per unit. Weibull models time-to-first-failure. If you repair equipment and track multiple failures on the same unit, you need recurrence models or repairable system analysis, not standard Weibull. The independence assumption breaks when units experience repeated failures.

Step 1: Collect the Right Data (Most Failures Happen Here)

Weibull analysis fails most often from poor data collection, not mathematical errors. Before opening analysis software, verify you have the correct data structure and quality.

Required Data Elements

Time-to-event for each unit. This is operating hours, cycles, mileage, or calendar time from start of exposure until failure or last observation. Critical: use the same time scale for all units. Don't mix calendar days for some units and operating hours for others.

Event status for each unit. Binary indicator: 1 for failed units, 0 for censored units (still operating or lost to follow-up). This distinguishes units that actually failed from those where you only know they survived past a certain point.

Failure mode identification (when relevant). If you're analyzing bearing failures specifically, exclude units that failed from other causes. Mixed failure modes create composite distributions that confuse interpretation. Root cause analysis determines failure modes before statistical analysis begins.

Common Data Collection Mistakes and Corrections

Mistake: Using calendar time when operating time matters. Two identical pumps installed the same day fail at different calendar times because one runs 24/7 while the other runs 8 hours daily. Calendar time creates artificial variation. Track actual operating hours or cycles.

Correction: Install hour meters or cycle counters. If historical data lacks this, estimate operating time from production records. Imperfect operating time estimates beat precise but irrelevant calendar times.

Mistake: Discarding censored observations. You only analyze failed units, treating unfailed units as "not useful yet." This throws away information and biases results toward shorter failure times, making reliability look worse than reality.

Correction: Record censored observations with their survival time and event status = 0. A pump running 1200 hours without failure tells you something. It survived at least 1200 hours. Weibull methods use this information properly.

Mistake: Mixing different stress levels without accounting for it. Units operating at different temperatures, loads, or environments have different failure distributions. Combining them assumes all operate under identical conditions.

Correction: Either stratify analysis by operating conditions (analyze high-temp separately from low-temp), or use accelerated life testing methods that explicitly model stress effects. Don't pool data from fundamentally different environments.

Mistake: Including early-life handling failures with wear-out failures. Units damaged during shipping or installation fail for different reasons than units wearing out from use. Mixing these modes obscures both patterns.

Correction: Define a burn-in period or qualification phase. Exclude failures from an early window you define in advance, or analyze early failures separately as installation/quality issues distinct from operational reliability.

Minimum Sample Size Reality Check

Weibull analysis can work with small samples if you handle censoring correctly, but the intervals will be wide. These are rough rules of thumb, not hard limits. Always read the confidence interval for your own data.

The result depends on the data, how many units are still in the study, and the choice at hand. Give a range with each estimate.

Remember: failures, not total units, drive most of the precision. Censored observations add information, but the failures carry most of it.

Step 2: Plot Your Data Before Calculating Anything

Jumping straight to parameter estimation misses the insights visible in properly constructed plots. Weibull probability plots reveal failure patterns, identify outliers, and show whether a Weibull distribution fits your data, all before touching mathematical formulas.

Creating Weibull Probability Plots

The plot code below uses failed units only. It does not count units still in the study. A fit for those units must use how long each was watched and whether it failed. A Weibull probability plot uses special axis scaling that transforms the Weibull cumulative distribution into a straight line. Deviations from linearity indicate Weibull distribution doesn't fit your data.

# Python implementation with matplotlib and scipy
import numpy as np
import matplotlib.pyplot as plt
from scipy import stats

# Public data: millions of revolutions to failure for 23 ball bearings
# (Lieblein and Zelen, 1956; also printed in Lawless, 2003)
failure_times = np.array([17.88, 28.92, 33.00, 41.52, 42.12, 45.60, 48.80, 51.84,
                          51.96, 54.12, 55.56, 67.80, 68.64, 68.64, 68.88, 84.12,
                          93.12, 98.64, 105.12, 105.84, 127.92, 128.04, 173.40])

# Rank and calculate plotting positions (median rank)
n = len(failure_times)
ranks = np.arange(1, n+1)
median_ranks = (ranks - 0.3) / (n + 0.4)

# Create Weibull probability plot
fig, ax = plt.subplots(figsize=(10, 6))

# Transform to log-log scale for linearity
x = np.log(failure_times)
y = np.log(-np.log(1 - median_ranks))

ax.scatter(x, y, alpha=0.6, s=50)
ax.set_xlabel('ln(Time)', fontsize=12)
ax.set_ylabel('ln(-ln(1-F(t)))', fontsize=12)
ax.set_title('Weibull Probability Plot', fontsize=14)
ax.grid(True, alpha=0.3)

# Fit line to extract parameters
slope, intercept = np.polyfit(x, y, 1)
beta = slope  # Shape parameter
eta = np.exp(-intercept/slope)  # Characteristic life

# Add fitted line
x_line = np.linspace(x.min(), x.max(), 100)
y_line = slope * x_line + intercept
ax.plot(x_line, y_line, 'r--', linewidth=2,
        label=f'β={beta:.2f}, η={eta:.1f}')
ax.legend()

plt.tight_layout()
plt.show()

# How straight is the line? (1.0 is perfectly straight)
r = np.corrcoef(x, y)[0, 1]
print(f"line fit: beta={beta:.2f}, eta={eta:.1f}, R-squared={r**2:.3f}")
# Output when run:
# line fit: beta=2.18, eta=81.6, R-squared=0.970

The 23 points sit close to one straight line (R-squared 0.97), so a single Weibull curve is a fair description of this data. The line gives a first guess of β = 2.18 and η = 81.6 million revolutions. Step 3 refines these with maximum likelihood, which is the better method once some units are still running.

What to Look For in Probability Plots

Straight line = good fit. Data points falling close to a straight line suggest a Weibull distribution fits your failures. That gives you reason to trust the parameter estimates, though a straight line is a visual check and not a proof.

Curvature = distribution mismatch or mixed modes. Systematic upward or downward curvature suggests Weibull doesn't fit. Upward curvature at high times indicates log-normal might fit better. S-shaped curves often mean mixed failure modes, two different mechanisms creating distinct populations.

Outliers = investigate root causes. Points far from the line represent unusual failures. A cluster of very early failures suggests quality defects. Extremely late failures might indicate a different usage pattern or superior manufacturing for those specific units. Don't automatically remove outliers, understand them first.

Slope = shape parameter β. Steep slope (β > 1) means increasing failure rate, wear-out dominates. Gentle slope (β < 1) means decreasing failure rate, infant mortality or quality problems. Slope near 1 means constant failure rate, random events.

The Quick Plot Check

Before proceeding with analysis, check the plot: do points fall reasonably close to a straight line? If yes, continue. If no, investigate why before calculating parameters. A curved probability plot suggests the Weibull fit may be poor, and parameter estimates may then be biased.

Step 3: Calculate Parameters That Drive Decisions

Weibull analysis produces two parameters that determine your reliability strategy. Understanding what these numbers mean, and how to act on them, matters more than calculation mechanics.

Shape Parameter (β): Your Failure Pattern Fingerprint

The shape parameter reveals whether you're fighting infant mortality, random failures, or wear-out. This distinction determines where you invest improvement resources.

β < 1 (Decreasing failure rate): Infant mortality dominates. Failures occur early in life then decline. This indicates:

Action: Implement burn-in testing to catch defects before shipping. Improve incoming inspection for critical components. Review assembly procedures for common early-failure units. These failures are preventable through quality improvements, not maintenance programs.

β ≈ 1 (Constant failure rate): Random failures with no time dependence. Probability of failure tomorrow equals probability next year. This indicates:

Action: Preventive maintenance provides limited benefit, failures aren't predictable by age. Focus on rapid repair and spare parts availability. Design for replaceability rather than prevention. Time-based maintenance wastes resources; condition-based monitoring adds value.

β > 1 (Increasing failure rate): Wear-out dominates. Failure probability increases with age. This indicates:

Action: Time-based preventive maintenance is cost-effective. Replace components before failure based on age. Calculate optimal replacement intervals balancing maintenance costs against failure consequences. Higher β values can make preventive replacement more economical, depending on the costs.

Characteristic Life (η): When Failures Happen

Characteristic life represents the time at which 63.2% of units have failed (for any β value). This provides a scale-free comparison across different distributions.

More useful for business decisions: the median life (time when 50% have failed) and B10 life (time when 10% have failed). These translate directly to warranty exposure and spare parts requirements.

# Calculate key lifetime percentiles from Weibull parameters
def weibull_percentile(p, beta, eta):
    """
    Calculate time when p fraction have failed
    p: failure fraction (0.1 for B10, 0.5 for median)
    beta: shape parameter
    eta: characteristic life
    """
    return eta * (-np.log(1 - p))**(1/beta)

# Bearing fit from the maximum likelihood step below: β=2.103, η=81.9
# (the text rounds β to 2.10; units: millions of revolutions)
beta = 2.103
eta = 81.9

b10 = weibull_percentile(0.10, beta, eta)
b50 = weibull_percentile(0.50, beta, eta)
b90 = weibull_percentile(0.90, beta, eta)

print(f"B10 life: {b10:.1f} million revolutions - 10% failed")
print(f"B50 life (median): {b50:.1f} million revolutions - 50% failed")
print(f"B90 life: {b90:.1f} million revolutions - 90% failed")

# Output when run:
# B10 life: 28.1 million revolutions - 10% failed
# B50 life (median): 68.8 million revolutions - 50% failed
# B90 life: 121.8 million revolutions - 90% failed

Look at how the numbers compare to the plain average of the 23 bearings, which is 72.2 million revolutions. The average hides the early failures. One bearing in ten is gone by 28.1 million revolutions, less than half the median. That early tail is what a warranty has to pay for.

Use B10 life for warranty period decisions. You're guaranteeing products survive this long. Use median life for maintenance planning: half your fleet needs attention by this point. Use B90 for spare parts inventory. You'll need replacements for 90% of units by this time.

Confidence Intervals: Acknowledging Uncertainty

Parameter estimates from limited data have uncertainty. Confidence intervals quantify this uncertainty, preventing overconfident decisions based on small samples.

The lifelines package fits the Weibull by maximum likelihood and handles units that have not failed. Set the event flag to 0 for a unit still running. In this data set every bearing failed, so every flag is 1.

from lifelines import WeibullFitter

wf = WeibullFitter().fit(failure_times, event_observed=np.ones(len(failure_times)))
ci = wf.summary[["coef", "coef lower 95%", "coef upper 95%"]]
print(f"Shape β: {wf.rho_:.2f}  (95% CI {ci.loc['rho_'].iloc[1]:.2f} to {ci.loc['rho_'].iloc[2]:.2f})")
print(f"Scale η: {wf.lambda_:.1f}  (95% CI {ci.loc['lambda_'].iloc[1]:.1f} to {ci.loc['lambda_'].iloc[2]:.1f})")

# Output when run:
# Shape β: 2.10  (95% CI 1.46 to 2.75)
# Scale η: 81.9  (95% CI 65.0 to 98.7)

The R survival package gives the same answer: survreg(Surv(t, e) ~ 1, dist = "weibull") returns shape 1/scale = 2.10 and characteristic life 81.9. The intervals are wide. With only 23 bearings, the shape could plausibly be anywhere from about 1.5 to 2.8. Every value in that range still means wear-out (β above 1), so the direction of the decision holds, but a precise B10 life does not.

The test of censoring is easy to run. Pretend the test stopped at 100 million revolutions. Five bearings (105.12, 105.84, 127.92, 128.04, 173.40) are then still running. Fitting with those five marked as censored at 100 gives β = 2.24 and η = 80.3, close to the full-data answer of 2.10 and 81.9. That is the point of keeping survivors in the data: you can stop the test early and lose little.

Report confidence intervals alongside point estimates in presentations. Wide intervals signal "collect more data before making expensive decisions." Narrow intervals justify confident action. This transparency builds trust with stakeholders.

Step 4: Translate Parameters Into Business Decisions

Parameters mean nothing until converted into actions. This section maps Weibull results to specific business decisions across common reliability challenges.

Decision 1: Set Warranty Periods That Balance Cost and Customer Satisfaction

Your warranty period determines both customer confidence and financial exposure. Too short, customers perceive poor quality. Too long, you pay for failures you didn't need to cover.

Decision framework: Compare a few candidate warranty lengths against the share of units that may fail by each, and weigh that against cost. The choice depends on the data and the business.

# Calculate warranty cost exposure
def warranty_cost_analysis(beta, eta, warranty_period, population, cost_per_failure):
    """
    Estimate warranty costs based on Weibull parameters
    """
    # Probability of failure within warranty
    p_failure = 1 - np.exp(-(warranty_period/eta)**beta)

    # Expected failures
    expected_failures = population * p_failure

    # Total cost
    total_cost = expected_failures * cost_per_failure

    return {
        'warranty_period': warranty_period,
        'failure_probability': p_failure,
        'expected_failures': expected_failures,
        'total_cost': total_cost,
        'cost_per_unit': total_cost / population
    }

# Example: Setting warranty for motor population
beta = 2.8  # Wear-out pattern
eta = 2400  # Characteristic life in hours

# Evaluate warranty options
for warranty_hrs in [500, 1000, 1500, 2000]:
    result = warranty_cost_analysis(beta, eta, warranty_hrs,
                                   population=10000, cost_per_failure=450)
    print(f"\n{warranty_hrs} hour warranty:")
    print(f"  Failure probability: {result['failure_probability']:.1%}")
    print(f"  Expected failures: {result['expected_failures']:.0f}")
    print(f"  Total cost: ${result['total_cost']:,.0f}")
    print(f"  Cost per unit: ${result['cost_per_unit']:.2f}")

# Output when run (the 10,000 units and $450 per failure are assumed inputs):
# 500 hour warranty:  1.2% fail, 123 failures,  $55,342 total,  $5.53 per unit
# 1000 hour warranty: 8.3% fail, 826 failures,  $371,571 total, $37.16 per unit
# 1500 hour warranty: 23.5% fail, 2352 failures, $1,058,615 total, $105.86 per unit
# 2000 hour warranty: 45.1% fail, 4513 failures, $2,030,830 total, $203.08 per unit

Doubling the warranty from 1000 to 2000 hours does not double the cost. It multiplies it by about 5.5, because with β = 2.8 the failure risk climbs fast with age. That is the reason to read β before you quote a warranty length. To use the bearing data instead, put in β = 2.10 and η = 81.9: a warranty of 28.1 million revolutions would be expected to cover about 10% of units.

Decision 2: Schedule Preventive Maintenance at Optimal Intervals

Preventive maintenance only makes economic sense when β > 1. Calculate the interval that minimizes total costs, balancing planned maintenance expenses against failure consequences.

The standard rule is age replacement: swap the part at age T, or sooner if it fails. The cost per unit of life at T is the expected cost of one cycle divided by the expected length of one cycle. Find the T where that ratio is lowest.

from scipy.integrate import quad
from scipy.optimize import minimize_scalar

def optimal_replacement_age(beta, eta, planned_cost, failure_cost):
    """Age T that minimizes cost per unit of life. Needs beta > 1."""
    if beta <= 1:
        return None   # no wear-out, so replacing by age does not help

    R = lambda t: np.exp(-(t / eta) ** beta)          # survival at age t

    def cost_rate(T):
        cycle_cost = planned_cost * R(T) + failure_cost * (1 - R(T))
        cycle_length = quad(R, 0, T)[0]               # expected life up to T
        return cycle_cost / cycle_length

    best = minimize_scalar(cost_rate, bounds=(0.05 * eta, 3 * eta), method="bounded")
    run_to_failure = failure_cost / quad(R, 0, np.inf)[0]
    return best.x, cost_rate(best.x), run_to_failure

# Bearing fit (millions of revolutions). The two costs are ASSUMED inputs:
# $200 for a planned swap, $3,500 for a failure in service.
T, rate, rtf = optimal_replacement_age(2.10, 81.9, planned_cost=200, failure_cost=3500)
print(f"Replace at {T:.1f} million revolutions; {np.exp(-(T/81.9)**2.10):.1%} of bearings still alive then")
print(f"Cost per million revolutions: ${rate:.2f} vs ${rtf:.2f} run-to-failure")

# Output when run:
# Replace at 20.7 million revolutions; 94.6% of bearings still alive then
# Cost per million revolutions: $18.62 vs $48.25 run-to-failure

With these assumed costs, swapping at 20.7 million revolutions costs about 61% less per revolution than waiting for failures. The answer depends on the cost ratio. Keep the $200 planned cost and drop the failure cost to $1,000 and the best age moves to 41.2 million revolutions with a saving of about 30%. At $500 the best age is 67.7 and the saving is about 10%. If a failure costs little more than a planned swap, run to failure is fine. Replace the assumed costs with your own before you act.

Decision 3: Compare Suppliers Without Fooling Yourself

Say Supplier A's parts fit η = 2800 hours and Supplier B's fit η = 3200 hours. Is B really better, or is this luck of the draw? The bearing fit above shows why you must ask: with 23 units, the 95% interval for η ran from 65.0 to 98.7, a spread of about 40% of the estimate. A 14% gap between two suppliers is well inside that kind of noise.

Fit each supplier on its own, keep the units that have not failed (flag 0), and compare the intervals. If they overlap a lot, you do not have enough evidence to switch. For a formal test that respects censoring, use a log-rank test (lifelines.statistics.logrank_test or R's survdiff). Do not use a rank-sum test on failed units only, because it throws away the survivors and makes the longer-lived supplier look worse than it is.

Also set a size for the gain that would matter to you before you look, such as a 10% longer B10 life. A small gain can be statistically clear and still not worth a price premium.

Worked Example Summary: 23 Ball Bearings

The steps above ran on one real data set. Lieblein and Zelen (1956) tested 23 deep-groove ball bearings to failure and recorded the millions of revolutions each one lasted. The data is reprinted in many textbooks, so you can check every number here yourself. Here is the whole result in one place.

QuantityResultHow it was found
Bearings tested, all failed23Source data
Plain average life72.2 million revolutionsMean of the 23 times
Probability plot straightnessR-squared 0.970Median ranks, Step 2 code
Shape β2.10 (95% CI 1.46 to 2.75)Maximum likelihood, lifelines and R survreg agree
Characteristic life η81.9 (95% CI 65.0 to 98.7)Maximum likelihood
B10 life28.1 million revolutionsη(-ln 0.9)^(1/β)
Median life68.8 million revolutionsη(ln 2)^(1/β)
B90 life121.8 million revolutionsη(-ln 0.1)^(1/β)
Chance of failing by 40 million revolutions19.9%1 - exp(-(40/81.9)^2.10)
Fit if the test stopped at 100 (5 bearings censored)β 2.24, η 80.3Same model with censoring

What the numbers say. β is 2.10 and even the low end of its interval is above 1, so these bearings wear out with age. The failure risk grows as the bearings get older. That makes age-based replacement worth testing (Decision 2). The B10 life of 28.1 is far below the average of 72.2, so quoting the average as a warranty length would badly understate early failures.

What they do not say. This is one test of 23 bearings from the 1950s, on one design. It tells you how this kind of analysis works. It does not tell you how your parts will behave. The costs in Decisions 1 and 2 are assumptions chosen to show the method.

Check It Yourself

In R: library(survival); survreg(Surv(t, e) ~ 1, data = d, dist = "weibull") on the 23 times above, with e = 1 for every row. The shape is 1 / fit$scale and the characteristic life is exp(coef(fit)). You should get 2.10 and 81.9.

Handling Special Cases and Edge Conditions

Real-world reliability data rarely matches textbook examples. These special cases require modified approaches to maintain analytical validity.

Mixed Failure Modes: When One Distribution Isn't Enough

Equipment fails from multiple mechanisms: bearings wear out, seals leak, electronics fail randomly. Combining all failures into one Weibull distribution creates a poor fit and misleading parameters.

Identification: Probability plots show distinct slopes for different time ranges, or S-shaped curvature indicating population mixture. Root cause analysis reveals multiple failure mechanisms.

Solution: Separate failures by mode and analyze each independently. If your failures include bearing, seal and electrical failures, create a separate Weibull analysis for each mode. This reveals which modes drive reliability and where improvements deliver maximum impact.

For each mode, treat units that failed from a different cause as censored at their failure time (event flag 0), then fit the Weibull on that mode alone, as in Step 3. The fits for each mode are then read the same way: its own β, its own η, its own B10.

Competing risks models provide more sophisticated analysis when you need to predict which failure mode occurs first and how eliminating one mode affects overall reliability. Use specialized software like R's survival package for competing risks analysis.

Heavily Censored Data: Extracting Signal from Limited Failures

Suppose you tested 200 units for 1000 hours each, but only 8 failures occurred. Can you trust the analysis?

Yes, with caveats. Maximum likelihood estimation handles censoring properly, extracting information from both failures and survivors. Your 192 censored observations contribute. They tell you at least 192 units survived 1000 hours.

Limitations: Precision decreases with heavy censoring. Report wide confidence intervals reflecting this uncertainty. Avoid extrapolating beyond the test duration. You have no information about behavior past 1000 hours.

Improved approach: Use accelerated life testing. Test some units at higher stress (temperature, load, cycling rate) to generate more failures quickly, then use physics-based models to translate results to normal operating conditions.

Left Truncation: When You Don't Observe Early Failures

You inherit a reliability tracking system that started monitoring 500 pumps already in service for 6 months. Pumps that failed in the first 6 months aren't in your dataset. This left truncation biases estimates.

Solution: Use left-truncated Weibull methods that account for delayed entry. In survival analysis software, specify both entry time and failure/censoring time for each unit.

To see the effect, make fake data where the truth is known: 4,000 units with true shape 2.0 and scale 300, where only units that survived past 100 are ever observed.

import numpy as np
from lifelines import WeibullFitter

rng = np.random.default_rng(1)
life = 300 * rng.weibull(2.0, 4000)      # true beta = 2.0, eta = 300
seen = life[life > 100]                  # units that failed before 100 are never recorded
entry = np.full(len(seen), 100.0)        # everyone entered observation at age 100

naive = WeibullFitter().fit(seen, np.ones(len(seen)))
fixed = WeibullFitter().fit(seen, np.ones(len(seen)), entry=entry)
print(f"Ignoring entry time: beta={naive.rho_:.2f}, eta={naive.lambda_:.0f}")
print(f"Using entry time:    beta={fixed.rho_:.2f}, eta={fixed.lambda_:.0f}")

# Output when run (true values are 2.0 and 300):
# Ignoring entry time: beta=2.45, eta=327
# Using entry time:    beta=2.04, eta=302

Ignoring the entry time makes the parts look more durable and the wear-out look sharper than they are, because the early failures are missing from the file. Pass the entry age to the fit (the entry argument in lifelines) whenever units join the data after the start of exposure.

Interval Censoring: When You Only Know Failures Occurred Between Inspections

Monthly inspections reveal failures, but exact failure time between inspections is unknown. Unit inspected at day 30 (functioning) and day 60 (failed) had failure somewhere in that 30-day window.

Solution: Interval-censored Weibull methods treat failure time as falling within an interval rather than at a point. Software packages like R's icenReg or Python's lifelines handle interval censoring.

If inspection intervals are short relative to characteristic life, you can approximate by using interval midpoints. For longer intervals, proper interval-censored methods prevent bias.

From Weibull Parameters to Organizational Impact

Weibull analysis succeeds when it changes decisions, not just produces parameters. The shape parameter β tells you where to invest: quality control for β < 1, preventive maintenance for β > 1, and rapid response for β ≈ 1. The characteristic life η sets the timeline for warranty periods, maintenance schedules, and spare parts requirements.

The method has four steps: collect the right data including units that have not failed, plot before calculating, estimate the parameters with confidence intervals, and turn them into decisions. On the 23 bearings that path gave a shape of 2.10, a B10 life of 28.1 million revolutions against an average of 72.2, and (under assumed costs) an age to swap parts that cuts cost per revolution by about 61%.

Start with data you already collect: warranty claims, maintenance records, test results. Structure it with time-to-event and failure indicators. Then ask the business questions: Should we extend the warranty? Should we replace parts at a set age? Is a second supplier really better, or is the gap inside the noise? Each answer needs your own costs and your own data, and each comes with an interval that tells you how sure to be.

If your units are customers and the event is a cancellation, the same model applies. You can try it on your own file with the free survival analysis tool.

Sources

Reviewed and re-run November 2, 2026 by the MCP Analytics Team. Original publication March 1, 2026.

Your turn

Bring your own data and the question you actually need answered.

MCP AnalyticsData science by email Send us your data and your question, and we will reply. ds@mcpanalytics.ai

Frequently Asked Questions

What does the Weibull shape parameter tell me about my failure pattern?

The shape parameter (β) determines your failure pattern: β < 1 means decreasing failure rate (infant mortality), β = 1 means constant failure rate (random failures), and β > 1 means increasing failure rate (wear-out). A bearing with β = 3.2 shows accelerating wear-out requiring preventive maintenance, while electronics with β = 0.7 indicate early-life defects requiring quality improvements. This single number tells you whether to focus on design improvements, quality control, or preventive maintenance schedules.

How many failures do I need for reliable Weibull analysis?

There is no fixed number, since it depends on how tight an answer you need. Many reliability texts treat 15 to 20 failures as a rough floor, and more failures give narrower intervals. In our bearing example, 23 failures gave a shape interval of 1.46 to 2.75: enough to say "wear-out", not enough for a precise B10 life. Check the interval, not a rule of thumb. You can use censored data (unfailed units) to supplement actual failures. These contribute information even though they haven't failed. With only 10 failures from testing 100 units, you still have valuable information from the 90 survivors. The key is proper handling of censored observations using maximum likelihood estimation, not waiting for everything to fail.

When should I use Weibull analysis instead of other reliability methods?

Use Weibull when you need to model time-to-failure with changing hazard rates, predict warranty costs before they occur, optimize maintenance schedules based on wear-out patterns, or analyze both failed and unfailed units together. Choose exponential distribution for constant failure rates (β = 1), log-normal when the logarithm of life is roughly symmetric, or Cox regression when you need to compare multiple factors simultaneously without assuming a specific distribution form.

Can Weibull analysis predict individual component failure times?

No. Weibull provides probability distributions for populations, not deterministic predictions for individual units. For example, a fit might say that 10% of components may fail by 500 hours and 50% by 1200 hours (made-up values), but cannot predict when unit #A47392 specifically will fail. Use these population probabilities for maintenance scheduling (plan for median life), spare parts inventory (stock for B90 life), and warranty reserve planning (budget for expected failures) rather than individual component predictions.

How do I handle mixed failure modes in Weibull analysis?

Mixed failure modes (e.g., bearing wear plus electrical shorts) violate the single-distribution assumption and create poor fits. First, identify failure modes through root cause analysis of each failed unit. Then either model each mode separately using competing risks methods (analyzing bearing failures independently from electrical failures), or fit mixture Weibull models with multiple shape parameters. Plotting failures by mode on probability paper reveals mixing. You'll see multiple distinct slopes or S-shaped curvature rather than a single straight line. Separate analysis by mode reveals which mechanisms drive reliability and where improvements provide maximum impact.