diff --git a/.travis.yml b/.travis.yml index 3b0c9d58c..a84b897e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,10 +8,10 @@ env: matrix: - export PANDAS_VERSION=0.23.4 && export NUMPY_VERSION=1.17.0 - export PANDAS_VERSION=0.24.1 && export NUMPY_VERSION=1.17.0 - - export PANDAS_VERSION=0.25.0 && export NUMPY_VERSION=1.17.0 - - export NUMPY_VERSION=1.16.4 && export PANDAS_VERSION=0.25.0 - - export NUMPY_VERSION=1.15.4 && export PANDAS_VERSION=0.25.0 - - export NUMPY_VERSION=1.17.0 && export PANDAS_VERSION=0.25.0 + - export PANDAS_VERSION=0.25.1 && export NUMPY_VERSION=1.17.0 + - export NUMPY_VERSION=1.16.4 && export PANDAS_VERSION=0.25.1 + - export NUMPY_VERSION=1.15.4 && export PANDAS_VERSION=0.25.1 + - export NUMPY_VERSION=1.17.0 && export PANDAS_VERSION=0.25.1 before_install: - ls # - sudo apt-get update diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ae93ef43..dc0a33d74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ ### Changelog +#### 0.22.4 + +##### New features + - Some performance improvements to regression models. + +##### Bug fixes + - Fixed issue where `concordance_index` would never exit if NaNs in dataset. + + #### 0.22.3 ##### New features diff --git a/lifelines/fitters/cox_time_varying_fitter.py b/lifelines/fitters/cox_time_varying_fitter.py index 98f806b3e..ac918f35a 100644 --- a/lifelines/fitters/cox_time_varying_fitter.py +++ b/lifelines/fitters/cox_time_varying_fitter.py @@ -77,8 +77,6 @@ class CoxTimeVaryingFitter(BaseFitter): the strata provided standard_errors_: Series the standard errors of the estimates - score_: float - the concordance index of the model. baseline_cumulative_hazard_: DataFrame baseline_survival_: DataFrame """ diff --git a/lifelines/utils/concordance.py b/lifelines/utils/concordance.py index 581d99913..9fc98b902 100644 --- a/lifelines/utils/concordance.py +++ b/lifelines/utils/concordance.py @@ -263,4 +263,9 @@ def _preprocess_scoring_data(event_times, predicted_scores, event_observed): if event_observed.shape != event_times.shape: raise ValueError("Observed events must be 1-dimensional of same length as event times") + # check for NaNs + for a in [event_times, predicted_scores, event_observed]: + if np.isnan(a).any(): + raise ValueError("NaNs detected in inputs, please correct or drop.") + return event_times, predicted_scores, event_observed diff --git a/tests/test_estimation.py b/tests/test_estimation.py index 81d029093..9f432d607 100644 --- a/tests/test_estimation.py +++ b/tests/test_estimation.py @@ -1392,6 +1392,34 @@ def test_BHF_fit_when_KMF_throws_an_error(self): bfh.fit(observations, entry=births) +class TestParametricRegressionFitter: + @pytest.fixture + def rossi(self): + rossi = load_rossi() + rossi["_int"] = 1.0 + return rossi + + def test_custom_weibull_model_gives_the_same_data_as_implemented_weibull_model(self, rossi): + class CustomWeibull(ParametricRegressionFitter): + + _fitted_parameter_names = ["lambda_", "rho_"] + + def _cumulative_hazard(self, params, T, Xs): + lambda_ = anp.exp(anp.dot(Xs["lambda_"], params["lambda_"])) + rho_ = anp.exp(anp.dot(Xs["rho_"], params["rho_"])) + + return (T / lambda_) ** rho_ + + cb = CustomWeibull() + wf = WeibullAFTFitter(fit_intercept=False) + + cb.fit(rossi, "week", "arrest", regressors={"lambda_": rossi.columns, "rho_": ["_int"]}) + wf.fit(rossi, "week", "arrest") + + assert_frame_equal(cb.summary.loc["lambda_"], wf.summary.loc["lambda_"], check_less_precise=2) + npt.assert_allclose(cb.log_likelihood_, wf.log_likelihood_) + + class TestRegressionFitters: @pytest.fixture def rossi(self):