From b8a4959f2fcbe89a6ed293185c8589e805b609b0 Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 14 Oct 2020 14:53:33 +0200 Subject: [PATCH 1/3] baseline hazard and baseline cumulative hazard confidence bounds added --- .../inspectionProfiles/profiles_settings.xml | 6 +++ .idea/modules.xml | 8 ++++ lifelines/fitters/cox_time_varying_fitter.py | 40 +++++++++++++++---- 3 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 000000000..105ce2da2 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..6a7ecdaa8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/lifelines/fitters/cox_time_varying_fitter.py b/lifelines/fitters/cox_time_varying_fitter.py index 29cfda683..19a9aa6d3 100644 --- a/lifelines/fitters/cox_time_varying_fitter.py +++ b/lifelines/fitters/cox_time_varying_fitter.py @@ -80,8 +80,12 @@ class CoxTimeVaryingFitter(SemiParametricRegressionFitter, ProportionalHazardMix the strata provided standard_errors_: Series the standard errors of the estimates + baseline_hazard_: DataFrame + baseline hazard with confidence bounds baseline_cumulative_hazard_: DataFrame + baseline cumulative hazard with confidence bounds baseline_survival_: DataFrame + baseline survival with confidence bounds """ _KNOWN_MODEL = True @@ -225,7 +229,8 @@ def fit( normalize(X, self._norm_mean, self._norm_std), events, start, stop, weights ) self.confidence_intervals_ = self._compute_confidence_intervals() - self.baseline_cumulative_hazard_ = self._compute_cumulative_baseline_hazard(df, events, start, stop, weights) + self.baseline_hazard_ = self._compute_baseline_hazard(df, events, start, stop, weights) + self.baseline_cumulative_hazard_ = self._compute_baseline_cumulative_hazard() self.baseline_survival_ = self._compute_baseline_survival() self.event_observed = events self.start_stop_and_events = pd.DataFrame({"event": events, "start": start, "stop": stop}) @@ -788,14 +793,16 @@ def plot(self, columns=None, ax=None, **errorbar_kwargs): return ax - def _compute_cumulative_baseline_hazard(self, tv_data, events, start, stop, weights): # pylint: disable=too-many-locals + def _compute_baseline_hazard(self, tv_data, events, start, stop, weights): # pylint: disable=too-many-locals with warnings.catch_warnings(): warnings.simplefilter("ignore") hazards = self.predict_partial_hazard(tv_data).values unique_death_times = np.unique(stop[events.values]) - baseline_hazard_ = pd.DataFrame(np.zeros_like(unique_death_times), index=unique_death_times, columns=["baseline hazard"]) + baseline_hazard_ = pd.DataFrame(np.zeros_like(unique_death_times), index=unique_death_times, columns=["baseline_hazard"]) + variance_baseline_hazard_ = pd.DataFrame(np.zeros_like(unique_death_times), index=unique_death_times, columns= + ["variance_baseline_hazard"]) for t in unique_death_times: ix = (start.values < t) & (t <= stop.values) @@ -807,14 +814,33 @@ def _compute_cumulative_baseline_hazard(self, tv_data, events, start, stop, weig deaths = events_at_t & (stops_at_t == t) - death_counts = (weights_at_t.squeeze() * deaths).sum() # should always be atleast 1. + death_counts = (weights_at_t.squeeze() * deaths).sum() # should always be at least 1. + variance_baseline_hazard_.loc[t] = death_counts / hazards_at_t.sum()**2 baseline_hazard_.loc[t] = death_counts / hazards_at_t.sum() + # klein and moeschberger, 2013, p.283 + z = inv_normal_cdf(1 - self.alpha / 2) + ci_labels = ["%s_upper_%g" % ("baseline_hazard", 1 - self.alpha), "%s_lower_%g" % ("baseline_hazard", self.alpha)] + upper = baseline_hazard_.values * np.exp(+z * np.sqrt(variance_baseline_hazard_.values) / baseline_hazard_.values) + lower = baseline_hazard_.values * np.exp(-z * np.sqrt(variance_baseline_hazard_.values) / baseline_hazard_.values) + baseline_hazard_[ci_labels[0]] = upper + baseline_hazard_[ci_labels[1]] = lower + + baseline_hazard_.loc[0] = [0,0,0] + baseline_hazard_ = baseline_hazard_.sort_index() + + return baseline_hazard_ - return baseline_hazard_.cumsum() + def _compute_baseline_cumulative_hazard(self): + baseline_cumulative_hazard = self.baseline_hazard_.cumsum() + baseline_cumulative_hazard.columns = baseline_cumulative_hazard.columns[:].str.replace("baseline_hazard", + "baseline_cumulative_hazard") + + return baseline_cumulative_hazard def _compute_baseline_survival(self): - survival_df = np.exp(-self.baseline_cumulative_hazard_) - survival_df.columns = ["baseline survival"] + survival_df = np.exp(-self.baseline_cumulative_hazard_.baseline_cumulative_hazard) + survival_df.name = "survival" + return survival_df def __repr__(self): From 8d5c90f36c8be9e6391ebbcfc1940f5906f75f0b Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 14 Oct 2020 14:59:44 +0200 Subject: [PATCH 2/3] rename survival fun --- lifelines/fitters/cox_time_varying_fitter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lifelines/fitters/cox_time_varying_fitter.py b/lifelines/fitters/cox_time_varying_fitter.py index 19a9aa6d3..5de45b07c 100644 --- a/lifelines/fitters/cox_time_varying_fitter.py +++ b/lifelines/fitters/cox_time_varying_fitter.py @@ -838,10 +838,10 @@ def _compute_baseline_cumulative_hazard(self): return baseline_cumulative_hazard def _compute_baseline_survival(self): - survival_df = np.exp(-self.baseline_cumulative_hazard_.baseline_cumulative_hazard) - survival_df.name = "survival" + survival = np.exp(-self.baseline_cumulative_hazard_.baseline_cumulative_hazard) + survival.name = "survival" - return survival_df + return survival def __repr__(self): classname = self._class_name From 118e6b9f7a306ab1adc5cf092fb1da69f6991bbe Mon Sep 17 00:00:00 2001 From: Stefan Date: Wed, 14 Oct 2020 15:02:19 +0200 Subject: [PATCH 3/3] remove from .idea etc --- .idea/inspectionProfiles/profiles_settings.xml | 6 ------ .idea/modules.xml | 8 -------- 2 files changed, 14 deletions(-) delete mode 100644 .idea/inspectionProfiles/profiles_settings.xml delete mode 100644 .idea/modules.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml deleted file mode 100644 index 105ce2da2..000000000 --- a/.idea/inspectionProfiles/profiles_settings.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 6a7ecdaa8..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file