/// <summary> /// Estimates an Empirical Hazards distribution considering event times and the outcome of the /// observed sample at the time of event, plus additional parameters for the hazard estimation. /// </summary> /// /// <param name="time">The time of occurrence for the event.</param> /// <param name="outcome">The outcome at the time of event (failure or censored).</param> /// <param name="weights">The weights associated with each event.</param> /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param> /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param> /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param> /// /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns> /// public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) { var dist = new EmpiricalHazardDistribution(survival); dist.Fit(time, weights, new EmpiricalHazardOptions { Outcome = outcome, Estimator = hazard, Ties = ties }); return(dist); }
void init(double[] times, double[] hazards, SurvivalEstimator estimator) { if (times == null) { times = new double[0]; } if (hazards == null) { hazards = new double[0]; } times = (double[])times.Clone(); hazards = (double[])hazards.Clone(); Array.Sort(times, hazards); for (int i = 0; i < times.Length - 1; i++) { if (times[i] > times[i + 1]) { throw new Exception(); } } if (times.Length > 0) { this.range = new DoubleRange(0, times[times.Length - 1]); this.survivals = new double[times.Length]; this.survivals[0] = 1; for (int i = 1; i < survivals.Length; i++) { survivals[i] = survivals[i - 1] * (1.0 - hazards[i - 1]); } } this.times = times; this.hazards = hazards; this.estimator = estimator; this.mean = null; this.variance = null; }
/// <summary> /// Initializes a new instance of the <see cref="EmpiricalHazardDistribution"/> class. /// </summary> /// /// <param name="times">The time steps.</param> /// <param name="lambdas">The hazard rates at the time steps.</param> /// <param name="estimator">The survival function estimator to be used. Default is /// <see cref="SurvivalEstimator.FlemingHarrington"/></param> /// public EmpiricalHazardDistribution(double[] times, double[] lambdas, SurvivalEstimator estimator) { if (times == null) { throw new ArgumentNullException("time"); } if (lambdas == null) { throw new ArgumentNullException("values"); } if (times.Length != lambdas.Length) { throw new DimensionMismatchException("time", "The time steps and value vectors must have the same length."); } init(times, lambdas, estimator); }
/// <summary> /// Estimates an Empirical Hazards distribution considering event times and the outcome of the /// observed sample at the time of event, plus additional parameters for the hazard estimation. /// </summary> /// /// <param name="time">The time of occurrence for the event.</param> /// <param name="outcome">The outcome at the time of event (failure or censored).</param> /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param> /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param> /// /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns> /// public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, SurvivalEstimator survival, HazardEstimator hazard) { return(Estimate(time, outcome, survival, hazard, EmpiricalHazardOptions.DefaultTies)); }
/// <summary> /// Fits the underlying distribution to a given set of observations. /// </summary> /// /// <param name="observations">The array of observations to fit the model against. The array /// elements can be either of type double (for univariate data) or /// type double[] (for multivariate data).</param> /// <param name="weights">The weight vector containing the weight for each of the samples.</param> /// <param name="options">Optional arguments which may be used during fitting, such /// as regularization constants and additional parameters.</param> /// public void Fit(double[] observations, double[] weights, SurvivalOptions options) { SurvivalOutcome[] outcome = null; double[] output = weights; var estimator = HazardEstimator.BreslowNelsonAalen; var ties = HazardTiesMethod.Breslow; if (options != null) { outcome = options.Outcome; var hazardOps = options as EmpiricalHazardOptions; if (hazardOps != null) { estimator = hazardOps.Estimator; ties = hazardOps.Ties; } } if (outcome == null) { outcome = Vector.Create(observations.Length, SurvivalOutcome.Failed); } if (output == null) { output = Vector.Create(observations.Length, 1.0); } if (estimator == HazardEstimator.KaplanMeier) { double[] times = observations.Distinct(); double[] hazards = new double[times.Length]; hazards[hazards.Length - 1] = 1; Array.Sort(times); // Compute an estimate of the hazard function using // the Kaplan-Meier estimator for the survival function double r = observations.Length; double d = 0; // Number of deaths double c = 0; // Number of censor for (int j = 0; j < times.Length; j++) { double t = times[j]; // Survivals until time t r = r - d - c; d = 0; c = 0; for (int i = 0; i < observations.Length; i++) { if (observations[i] == t) { if (outcome[i] == SurvivalOutcome.Failed) { d++; // Failure at time t } else { c++; // Censored at time t } } } hazards[j] = d / r; } this.init(times, hazards, this.estimator); return; } else if (estimator == HazardEstimator.BreslowNelsonAalen) { double[] survivals = new double[observations.Length]; Sort(ref observations, ref outcome, ref output); // Compute an estimate of the cumulative Hazard // function using the Breslow-Nelson-Aalen estimator double sum = 0; double d = 0; for (int i = 0; i < observations.Length; i++) { survivals[i] = 1; double t = observations[i]; double v = output[i]; var o = outcome[i]; sum += v; if (o == SurvivalOutcome.Censored) { d = 0; continue; } if (i > 0 && t != observations[i - 1]) { d = 0; } // Count the number of deaths at t if (o == SurvivalOutcome.Failed) { d++; // Deaths at time t } if (i < observations.Length - 1 && t == observations[i + 1] && outcome[i + 1] == SurvivalOutcome.Failed) { continue; } if (ties == HazardTiesMethod.Breslow) { survivals[i] = Math.Exp(-d / sum); } else { if (d == 1) { survivals[i] = Math.Pow(1 - v / sum, 1 / v); } else { survivals[i] = Math.Exp(-d / sum); } } } // Transform to hazards double[] hazards = new double[observations.Length]; for (int i = 0; i < hazards.Length; i++) { hazards[i] = -Math.Log(survivals[i]); } Array.Sort(observations, hazards); this.init(observations, hazards, this.estimator); return; } throw new ArgumentException(); }
/// <summary> /// Initializes a new instance of the <see cref="EmpiricalHazardDistribution"/> class. /// </summary> /// /// <param name="estimator">The survival function estimator to be used. Default is /// <see cref="SurvivalEstimator.FlemingHarrington"/></param> /// public EmpiricalHazardDistribution(SurvivalEstimator estimator) { init(null, null, estimator); }
/// <summary> /// Estimates an Empirical Hazards distribution considering event times and the outcome of the /// observed sample at the time of event, plus additional parameters for the hazard estimation. /// </summary> /// /// <param name="time">The time of occurrence for the event.</param> /// <param name="outcome">The outcome at the time of event (failure or censored).</param> /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param> /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param> /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param> /// /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns> /// public static EmpiricalHazardDistribution Estimate(double[] time, SurvivalOutcome[] outcome, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) { return(Estimate(time, outcome, null, survival, hazard, ties)); }
/// <summary> /// Estimates an Empirical Hazards distribution considering event times and the outcome of the /// observed sample at the time of event, plus additional parameters for the hazard estimation. /// </summary> /// /// <param name="time">The time of occurrence for the event.</param> /// <param name="outcome">The outcome at the time of event (failure or censored).</param> /// <param name="weights">The weights associated with each event.</param> /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param> /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param> /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param> /// /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns> /// public static EmpiricalHazardDistribution Estimate(double[] time, int[] outcome, double[] weights, SurvivalEstimator survival, HazardEstimator hazard, HazardTiesMethod ties) { return(Estimate(time, outcome.To <SurvivalOutcome[]>(), weights, survival, hazard, ties)); }
/// <summary> /// Estimates an Empirical Hazards distribution considering event times and the outcome of the /// observed sample at the time of event, plus additional parameters for the hazard estimation. /// </summary> /// /// <param name="time">The time of occurrence for the event.</param> /// <param name="weights">The weights associated with each event.</param> /// <param name="hazard">The hazard estimator to use. Default is <see cref="HazardEstimator.BreslowNelsonAalen"/>.</param> /// <param name="survival">The survival estimator to use. Default is <see cref="SurvivalEstimator.FlemingHarrington"/>.</param> /// <param name="ties">The method for handling event ties. Default is <see cref="HazardTiesMethod.Efron"/>.</param> /// /// <returns>The <see cref="EmpiricalHazardDistribution"/> estimated from the given data.</returns> /// public static EmpiricalHazardDistribution Estimate(double[] time, double[] weights = null, SurvivalEstimator survival = EmpiricalHazardOptions.DefaultSurvival, HazardEstimator hazard = EmpiricalHazardOptions.DefaultEstimator, HazardTiesMethod ties = EmpiricalHazardOptions.DefaultTies) { return(Estimate(time, (SurvivalOutcome[])null, weights, survival, hazard, ties)); }