lifelines 0.28.0__tar.gz → 0.29.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. {lifelines-0.28.0/lifelines.egg-info → lifelines-0.29.0}/PKG-INFO +5 -5
  2. {lifelines-0.28.0 → lifelines-0.29.0}/README.md +2 -2
  3. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/__init__.py +1 -1
  4. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/__init__.py +6 -6
  5. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/aalen_additive_fitter.py +2 -2
  6. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/cox_time_varying_fitter.py +1 -1
  7. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/coxph_fitter.py +6 -4
  8. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/mixins.py +3 -3
  9. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/nelson_aalen_fitter.py +1 -1
  10. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/npmle.py +1 -1
  11. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/piecewise_exponential_regression_fitter.py +1 -1
  12. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/generate_datasets.py +6 -6
  13. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/test_estimation.py +10 -10
  14. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/test_plotting.py +2 -2
  15. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/utils/test_utils.py +1 -1
  16. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/__init__.py +8 -8
  17. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/version.py +1 -1
  18. {lifelines-0.28.0 → lifelines-0.29.0/lifelines.egg-info}/PKG-INFO +5 -5
  19. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines.egg-info/requires.txt +2 -2
  20. {lifelines-0.28.0 → lifelines-0.29.0}/reqs/base-requirements.txt +2 -2
  21. {lifelines-0.28.0 → lifelines-0.29.0}/reqs/dev-requirements.txt +1 -1
  22. {lifelines-0.28.0 → lifelines-0.29.0}/LICENSE +0 -0
  23. {lifelines-0.28.0 → lifelines-0.29.0}/MANIFEST.in +0 -0
  24. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/__init__.py +0 -0
  25. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/calibration.py +0 -0
  26. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/CuZn-LeftCensoredDataset.csv +0 -0
  27. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/anderson.csv +0 -0
  28. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/c_botulinum_lag_phase.csv +0 -0
  29. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/canadian_senators.csv +0 -0
  30. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/dd.csv +0 -0
  31. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/dfcv_dataset.py +0 -0
  32. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/divorce.dat +0 -0
  33. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/g3.csv +0 -0
  34. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/gbsg2.csv +0 -0
  35. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/gehan.dat +0 -0
  36. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/holly_molly_polly.tsv +0 -0
  37. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/interval_diabetes.csv +0 -0
  38. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/kidney_transplant.csv +0 -0
  39. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/larynx.csv +0 -0
  40. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/lung.csv +0 -0
  41. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/lymph_node.csv +0 -0
  42. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/lymphoma.csv +0 -0
  43. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/merrell1955.csv +0 -0
  44. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/mice.csv +0 -0
  45. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/multicenter_aids_cohort.tsv +0 -0
  46. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/nh4.csv +0 -0
  47. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/panel_test.csv +0 -0
  48. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/psychiatric_patients.csv +0 -0
  49. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/recur.csv +0 -0
  50. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/regression.csv +0 -0
  51. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/rossi.csv +0 -0
  52. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/stanford_heart.csv +0 -0
  53. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/static_test.csv +0 -0
  54. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/datasets/waltons_dataset.csv +0 -0
  55. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/exceptions.py +0 -0
  56. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/aalen_johansen_fitter.py +0 -0
  57. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/breslow_fleming_harrington_fitter.py +0 -0
  58. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/crc_spline_fitter.py +0 -0
  59. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/exponential_fitter.py +0 -0
  60. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/generalized_gamma_fitter.py +0 -0
  61. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/generalized_gamma_regression_fitter.py +0 -0
  62. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/kaplan_meier_fitter.py +0 -0
  63. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/log_logistic_aft_fitter.py +0 -0
  64. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/log_logistic_fitter.py +0 -0
  65. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/log_normal_aft_fitter.py +0 -0
  66. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/log_normal_fitter.py +0 -0
  67. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/mixture_cure_fitter.py +0 -0
  68. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/piecewise_exponential_fitter.py +0 -0
  69. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/spline_fitter.py +0 -0
  70. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/weibull_aft_fitter.py +0 -0
  71. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/fitters/weibull_fitter.py +0 -0
  72. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/plotting.py +0 -0
  73. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/statistics.py +0 -0
  74. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/__init__.py +0 -0
  75. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/test_generate_datasets.py +0 -0
  76. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/test_npmle.py +0 -0
  77. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/test_statistics.py +0 -0
  78. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/utils/test_btree.py +0 -0
  79. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/tests/utils/test_concordance.py +0 -0
  80. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/btree.py +0 -0
  81. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/concordance.py +0 -0
  82. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/lowess.py +0 -0
  83. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/printer.py +0 -0
  84. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines/utils/safe_exp.py +0 -0
  85. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines.egg-info/SOURCES.txt +0 -0
  86. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines.egg-info/dependency_links.txt +0 -0
  87. {lifelines-0.28.0 → lifelines-0.29.0}/lifelines.egg-info/top_level.txt +0 -0
  88. {lifelines-0.28.0 → lifelines-0.29.0}/reqs/docs-requirements.txt +0 -0
  89. {lifelines-0.28.0 → lifelines-0.29.0}/setup.cfg +0 -0
  90. {lifelines-0.28.0 → lifelines-0.29.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lifelines
3
- Version: 0.28.0
3
+ Version: 0.29.0
4
4
  Summary: Survival analysis in Python, including Kaplan Meier, Nelson Aalen and regression
5
5
  Home-page: https://github.com/CamDavidsonPilon/lifelines
6
6
  Author: Cameron Davidson-Pilon
@@ -17,8 +17,8 @@ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: numpy<2.0,>=1.14.0
20
- Requires-Dist: scipy>=1.2.0
21
- Requires-Dist: pandas>=1.2.0
20
+ Requires-Dist: scipy>=1.7.0
21
+ Requires-Dist: pandas>=2.1
22
22
  Requires-Dist: matplotlib>=3.0
23
23
  Requires-Dist: autograd>=1.5
24
24
  Requires-Dist: autograd-gamma>=0.3
@@ -50,8 +50,8 @@ If you are new to survival analysis, wondering why it is useful, or are interest
50
50
 
51
51
  ## Contact
52
52
  - Start a conversation in our [Discussions room](https://github.com/CamDavidsonPilon/lifelines/discussions).
53
- - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion)
54
- - creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
53
+ - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion).
54
+ - Creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
55
55
 
56
56
  ## Development
57
57
 
@@ -24,8 +24,8 @@ If you are new to survival analysis, wondering why it is useful, or are interest
24
24
 
25
25
  ## Contact
26
26
  - Start a conversation in our [Discussions room](https://github.com/CamDavidsonPilon/lifelines/discussions).
27
- - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion)
28
- - creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
27
+ - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion).
28
+ - Creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
29
29
 
30
30
  ## Development
31
31
 
@@ -54,7 +54,7 @@ def load_multicenter_aids_cohort_study(**kwargs):
54
54
  """
55
55
  Originally in [1]::
56
56
 
57
- Siz: (78, 4)
57
+ Size: (78, 4)
58
58
 
59
59
  AIDSY: date of AIDS diagnosis
60
60
  W: years from AIDS diagnosis to study entry
@@ -18,7 +18,7 @@ from autograd.misc import flatten
18
18
  import autograd.numpy as anp
19
19
 
20
20
  from scipy.optimize import minimize, root_scalar
21
- from scipy.integrate import trapz
21
+ from scipy.integrate import trapezoid
22
22
  from scipy import stats
23
23
 
24
24
  import pandas as pd
@@ -573,7 +573,7 @@ class ParametricUnivariateFitter(UnivariateFitter):
573
573
 
574
574
  # convergence successful.
575
575
  # I still need to check for ~np.isnan(minimizing_results.x).any() since minimize will happily
576
- # return nans even when criteria is satisified.
576
+ # return nans even when criteria is satisfied.
577
577
  if minimizing_results and minimizing_results.success and ~np.isnan(minimizing_results.x).any():
578
578
  sol = utils._to_1d_array(minimizing_results.x)
579
579
  # pylint: disable=no-value-for-parameter
@@ -876,7 +876,7 @@ class ParametricUnivariateFitter(UnivariateFitter):
876
876
  length n, the end of the period the subject experienced the event in. If the value is equal to the corresponding value in lower_bound, then
877
877
  the individual's event was observed (not censored).
878
878
  event_observed: numpy array or pd.Series, optional
879
- length n, if left optional, infer from ``lower_bound`` and ``upper_cound`` (if lower_bound==upper_bound then event observed, if lower_bound < upper_bound, then event censored)
879
+ length n, if left optional, infer from ``lower_bound`` and ``upper_bound`` (if lower_bound==upper_bound then event observed, if lower_bound < upper_bound, then event censored)
880
880
  timeline: list, optional
881
881
  return the estimate at the values in timeline (positively increasing)
882
882
  label: string, optional
@@ -1925,7 +1925,7 @@ class ParametricRegressionFitter(RegressionFitter):
1925
1925
  def _fit_model(
1926
1926
  self, likelihood, Ts, Xs, E, weights, entries, fit_options, show_progress=False, user_supplied_initial_point=None
1927
1927
  ):
1928
- inital_points_as_arrays, unflatten_array_to_dict = self._prepare_initial_points(
1928
+ initial_points_as_arrays, unflatten_array_to_dict = self._prepare_initial_points(
1929
1929
  user_supplied_initial_point, Ts, E, entries, weights, Xs
1930
1930
  )
1931
1931
 
@@ -1939,7 +1939,7 @@ class ParametricRegressionFitter(RegressionFitter):
1939
1939
 
1940
1940
  minimum_ll = np.inf
1941
1941
  minimum_results = None
1942
- for _initial_point in inital_points_as_arrays:
1942
+ for _initial_point in initial_points_as_arrays:
1943
1943
 
1944
1944
  if _initial_point.shape[0] != Xs.columns.size:
1945
1945
  raise ValueError("initial_point is not the correct shape.")
@@ -2507,7 +2507,7 @@ class ParametricRegressionFitter(RegressionFitter):
2507
2507
  warnings.warn("""Approximating the expected value using trapezoid rule.\n""", exceptions.ApproximationWarning)
2508
2508
  subjects = utils._get_index(X)
2509
2509
  v = self.predict_survival_function(X, conditional_after=conditional_after)[subjects]
2510
- return pd.Series(trapz(v.values.T, v.index), index=subjects).squeeze()
2510
+ return pd.Series(trapezoid(v.values.T, v.index), index=subjects).squeeze()
2511
2511
 
2512
2512
  @property
2513
2513
  def median_survival_time_(self):
@@ -6,7 +6,7 @@ import time
6
6
  import numpy as np
7
7
  import pandas as pd
8
8
  from numpy.linalg import LinAlgError
9
- from scipy.integrate import trapz
9
+ from scipy.integrate import trapezoid
10
10
 
11
11
  from lifelines.fitters import RegressionFitter
12
12
  from lifelines.utils.printer import Printer
@@ -396,7 +396,7 @@ It's important to know that the naive variance estimates of the coefficients are
396
396
  """
397
397
  index = _get_index(X)
398
398
  t = self._index
399
- return pd.Series(trapz(self.predict_survival_function(X)[index].values.T, t), index=index)
399
+ return pd.Series(trapezoid(self.predict_survival_function(X)[index].values.T, t), index=index)
400
400
 
401
401
  def _compute_confidence_intervals(self):
402
402
  ci = 100 * (1 - self.alpha)
@@ -801,7 +801,7 @@ See https://stats.stackexchange.com/questions/11109/how-to-deal-with-perfect-sep
801
801
  hazards = self.predict_partial_hazard(tv_data).values
802
802
 
803
803
  unique_death_times = np.unique(stop[events.values])
804
- baseline_hazard_ = pd.DataFrame(np.zeros_like(unique_death_times), index=unique_death_times, columns=["baseline hazard"])
804
+ baseline_hazard_ = pd.DataFrame(np.zeros_like(unique_death_times).astype(float), index=unique_death_times, columns=["baseline hazard"])
805
805
 
806
806
  for t in unique_death_times:
807
807
  ix = (start.values < t) & (t <= stop.values)
@@ -9,7 +9,7 @@ import time
9
9
  from numpy import dot, einsum, log, exp, zeros, arange, multiply, ndarray
10
10
  import numpy as np
11
11
  from scipy.linalg import solve as spsolve, LinAlgError, norm, inv
12
- from scipy.integrate import trapz
12
+ from scipy.integrate import trapezoid
13
13
  from scipy import stats
14
14
  from pandas import DataFrame, Series, Index
15
15
  import pandas as pd
@@ -2514,7 +2514,7 @@ See https://stats.stackexchange.com/q/11109/11867 for more.\n",
2514
2514
  """
2515
2515
  subjects = utils._get_index(X)
2516
2516
  v = self.predict_survival_function(X, conditional_after=conditional_after)[subjects]
2517
- return pd.Series(trapz(v.values.T, v.index), index=subjects)
2517
+ return pd.Series(trapezoid(v.values.T, v.index), index=subjects)
2518
2518
 
2519
2519
  def _compute_baseline_hazard(self, partial_hazards: DataFrame, name: Any) -> pd.DataFrame:
2520
2520
  # https://stats.stackexchange.com/questions/46532/cox-baseline-hazard
@@ -3223,7 +3223,7 @@ class ParametricPiecewiseBaselinePHFitter(ParametricCoxModelFitter, Proportional
3223
3223
 
3224
3224
  for stratum, stratified_X in df.groupby(self.strata):
3225
3225
  log_lambdas_ = anp.array(
3226
- [0] + [self.params_[self._strata_labeler(stratum, i)][0] for i in range(2, self.n_breakpoints + 2)]
3226
+ [0] + [self.params_.loc[self._strata_labeler(stratum, i)].iloc[0] for i in range(2, self.n_breakpoints + 2)]
3227
3227
  )
3228
3228
  lambdas_ = np.exp(log_lambdas_)
3229
3229
 
@@ -3237,7 +3237,9 @@ class ParametricPiecewiseBaselinePHFitter(ParametricCoxModelFitter, Proportional
3237
3237
  return cumulative_hazard
3238
3238
 
3239
3239
  else:
3240
- log_lambdas_ = np.array([0] + [self.params_[param][0] for param in self._fitted_parameter_names if param != "beta_"])
3240
+ log_lambdas_ = np.array(
3241
+ [0] + [self.params_.loc[param].iloc[0] for param in self._fitted_parameter_names if param != "beta_"]
3242
+ )
3241
3243
  lambdas_ = np.exp(log_lambdas_)
3242
3244
 
3243
3245
  Xs = self.regressors.transform_df(df)
@@ -110,7 +110,7 @@ class ProportionalHazardMixin:
110
110
  axes = []
111
111
 
112
112
  for variable in self.params_.index.intersection(columns or self.params_.index):
113
- minumum_observed_p_value = test_results.summary.loc[variable, "p"].min()
113
+ minimum_observed_p_value = test_results.summary.loc[variable, "p"].min()
114
114
 
115
115
  # plot is done (regardless of test result) whenever `show_plots = True`
116
116
  if show_plots:
@@ -154,7 +154,7 @@ class ProportionalHazardMixin:
154
154
  plt.tight_layout()
155
155
  plt.subplots_adjust(top=0.90)
156
156
 
157
- if np.round(minumum_observed_p_value, 2) > p_value_threshold:
157
+ if np.round(minimum_observed_p_value, 2) > p_value_threshold:
158
158
  continue
159
159
 
160
160
  counter += 1
@@ -182,7 +182,7 @@ class ProportionalHazardMixin:
182
182
  print()
183
183
  print(
184
184
  "%d. Variable '%s' failed the non-proportional test: p-value is %s."
185
- % (counter, variable, format_p_value(4)(minumum_observed_p_value)),
185
+ % (counter, variable, format_p_value(4)(minimum_observed_p_value)),
186
186
  end="\n\n",
187
187
  )
188
188
 
@@ -200,7 +200,7 @@ class NelsonAalenFitter(UnivariateFitter):
200
200
  Parameters
201
201
  -----------
202
202
  bandwidth: float
203
- the bandwith used in the Epanechnikov kernel.
203
+ the bandwidth used in the Epanechnikov kernel.
204
204
 
205
205
  Returns
206
206
  -------
@@ -291,7 +291,7 @@ def reconstruct_survival_function(
291
291
 
292
292
  # First backfill at events between known observations
293
293
  # Second fill all events _outside_ known obs with running_sum
294
- return full_dataframe.combine_first(df).bfill().fillna(running_sum).clip(lower=0.0)
294
+ return full_dataframe.combine_first(df).astype(float).bfill().fillna(running_sum).clip(lower=0.0)
295
295
 
296
296
 
297
297
  def npmle_compute_confidence_intervals(left, right, mle_, alpha=0.05, samples=1000):
@@ -66,7 +66,7 @@ class PiecewiseExponentialRegressionFitter(ParametricRegressionFitter):
66
66
  coef_penalty = 0
67
67
  if self.penalizer > 0:
68
68
  for i in range(params_stacked.shape[1]):
69
- if not self._cols_to_not_penalize[i]:
69
+ if not self._cols_to_not_penalize.iloc[i]:
70
70
  coef_penalty = coef_penalty + (params_stacked[:, i]).var()
71
71
 
72
72
  return neg_ll + self.penalizer * coef_penalty
@@ -5,7 +5,7 @@ import pandas as pd
5
5
 
6
6
  from scipy import stats
7
7
  from scipy.optimize import newton
8
- from scipy.integrate import cumtrapz
8
+ from scipy.integrate import cumulative_trapezoid
9
9
 
10
10
  random = np.random
11
11
 
@@ -172,7 +172,7 @@ def constant_coefficients(d, timelines, constant=True, independent=0):
172
172
  timelines: the observational times
173
173
  constant: True for constant coefficients
174
174
  independent: the number of coffients to set to 0 (covariate is ind of survival), or
175
- a list of covariates to make indepent.
175
+ a list of covariates to make independent.
176
176
 
177
177
  returns a matrix (t,d+1) of coefficients
178
178
  """
@@ -187,7 +187,7 @@ def time_varying_coefficients(d, timelines, constant=False, independent=0, randg
187
187
  timelines: the observational times
188
188
  constant: True for constant coefficients
189
189
  independent: the number of coffients to set to 0 (covariate is ind of survival), or
190
- a list of covariates to make indepent.
190
+ a list of covariates to make independent.
191
191
  randgen: how scalar coefficients (betas) are sampled.
192
192
 
193
193
  returns a matrix (t,d+1) of coefficients
@@ -221,7 +221,7 @@ def generate_hazard_rates(n, d, timelines, constant=False, independent=0, n_bina
221
221
  n: the number of instances
222
222
  d: the number of covariates
223
223
  lifelines: the observational times
224
- constant: make the coeffients constant (not time dependent)
224
+ constant: make the coefficients constant (not time dependent)
225
225
  n_binary: the number of binary covariates
226
226
  model: from ["aalen", "cox"]
227
227
 
@@ -253,7 +253,7 @@ def generate_random_lifetimes(hazard_rates, timelines, size=1, censor=None):
253
253
  timelines: (t,) the observation times
254
254
  size: the number to return, per hardard rate
255
255
  censor: If True, adds uniform censoring between timelines.max() and 0
256
- If a postive number, censors all events above that value.
256
+ If a positive number, censors all events above that value.
257
257
  If (n,) np.array >=0 , censor elementwise.
258
258
 
259
259
 
@@ -308,7 +308,7 @@ def cumulative_integral(fx, x):
308
308
  fx: (n,d) numpy array, what you want to integral of
309
309
  x: (n,) numpy array, location to integrate over.
310
310
  """
311
- return cumtrapz(fx.T, x, initial=0).T
311
+ return cumulative_trapezoid(fx.T, x, initial=0).T
312
312
 
313
313
 
314
314
  def construct_survival_curves(hazard_rates, timelines):
@@ -2008,7 +2008,7 @@ class TestRegressionFitters:
2008
2008
  def test_fit_will_accept_object_dtype_as_event_col(self, regression_models_sans_strata_model, rossi):
2009
2009
  # issue #638
2010
2010
  rossi["arrest"] = rossi["arrest"].astype(object)
2011
- rossi["arrest"].iloc[0] = None
2011
+ rossi.loc[0, "arrest"] = None
2012
2012
 
2013
2013
  assert rossi["arrest"].dtype == object
2014
2014
  rossi = rossi.dropna()
@@ -2953,7 +2953,7 @@ class TestCoxPHFitter_SemiParametric:
2953
2953
  assert_frame_equal(cph.baseline_cumulative_hazard_, cph_scaled.baseline_cumulative_hazard_)
2954
2954
 
2955
2955
 
2956
- class TestCoxPHFitterPeices:
2956
+ class TestCoxPHFitterPieces:
2957
2957
  @pytest.fixture
2958
2958
  def cph(self):
2959
2959
  return CoxPHFitter(baseline_estimation_method="piecewise", breakpoints=[25])
@@ -3108,7 +3108,7 @@ class TestCoxPHFitter:
3108
3108
  cph.fit(df, "T", formula="C(cat)")
3109
3109
  assert cph.summary.shape[0] == 2
3110
3110
 
3111
- def test_trival_entry_col(self, rossi):
3111
+ def test_trivial_entry_col(self, rossi):
3112
3112
  cph_without_entry_summary = CoxPHFitter().fit(rossi, "week", "arrest").summary
3113
3113
  cphs_without_entry_summary = (
3114
3114
  CoxPHFitter(baseline_estimation_method="spline", n_baseline_knots=2).fit(rossi, "week", "arrest").summary
@@ -3125,7 +3125,7 @@ class TestCoxPHFitter:
3125
3125
  assert_frame_equal(cph_without_entry_summary, cph_with_entry_summary)
3126
3126
  assert_frame_equal(cphs_without_entry_summary, cphs_with_entry_summary)
3127
3127
 
3128
- def test_trival_entry_col_with_strata(self, rossi):
3128
+ def test_trivial_entry_col_with_strata(self, rossi):
3129
3129
  cph_without_entry_summary = CoxPHFitter().fit(rossi, "week", "arrest", strata=["fin"]).summary
3130
3130
 
3131
3131
  rossi["entry"] = 0
@@ -3466,7 +3466,7 @@ class TestCoxPHFitter:
3466
3466
  cph.fit(rossi, "week", "arrest")
3467
3467
  cph.check_assumptions(rossi)
3468
3468
 
3469
- def test_check_assumptions_thows_if_raise_on_fail_enalbed(self, cph, rossi):
3469
+ def test_check_assumptions_throws_if_raise_on_fail_enabled(self, cph, rossi):
3470
3470
  cph.fit(rossi, "week", "arrest")
3471
3471
  with pytest.raises(ProportionalHazardAssumptionError):
3472
3472
  cph.check_assumptions(rossi, p_value_threshold=0.05, raise_on_fail=True)
@@ -4169,7 +4169,7 @@ log-likelihood ratio test = 33.27 on 7 df
4169
4169
  expected = pd.Series({"var": 0.643})
4170
4170
  assert_series_equal(cph.summary["se(coef)"], expected, atol=0.01, check_names=False)
4171
4171
 
4172
- def test_robust_errors_with_less_trival_weights_is_the_same_as_R(self, regression_dataset):
4172
+ def test_robust_errors_with_less_trivial_weights_is_the_same_as_R(self, regression_dataset):
4173
4173
  """
4174
4174
  df <- data.frame(
4175
4175
  "var1" = c(0.209325, 0.693919, 0.443804, 0.065636, 0.386294),
@@ -4343,7 +4343,7 @@ log-likelihood ratio test = 33.27 on 7 df
4343
4343
  expected = 0.05
4344
4344
  assert abs(cph.log_likelihood_ratio_test().test_statistic - expected) < 0.01
4345
4345
 
4346
- def test_trival_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4346
+ def test_trivial_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4347
4347
  """
4348
4348
  df <- data.frame(
4349
4349
  "var1" = c(0.209325, 0.693919, 0.443804, 0.065636, 0.386294),
@@ -4374,7 +4374,7 @@ log-likelihood ratio test = 33.27 on 7 df
4374
4374
  expected_ll = -1.142397
4375
4375
  assert abs(cph.log_likelihood_ - expected_ll) < 0.001
4376
4376
 
4377
- def test_less_trival_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4377
+ def test_less_trivial_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4378
4378
  """
4379
4379
  df <- data.frame(
4380
4380
  "var1" = c(0.209325, 0.693919, 0.443804, 0.065636, 0.386294),
@@ -4402,7 +4402,7 @@ log-likelihood ratio test = 33.27 on 7 df
4402
4402
  expected = pd.Series({"var1": 6.690, "var2": 1.614})
4403
4403
  assert_series_equal(cph.summary["se(coef)"], expected, atol=0.01, check_names=False)
4404
4404
 
4405
- def test_non_trival_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4405
+ def test_non_trivial_float_weights_with_no_ties_is_the_same_as_R(self, regression_dataset):
4406
4406
  """
4407
4407
  df <- read.csv('.../lifelines/datasets/regression.csv')
4408
4408
  coxph(formula=Surv(T, E) ~ var1 + var2, data=df, weights=var3)
@@ -5588,7 +5588,7 @@ log-likelihood ratio test = 15.11 on 4 df
5588
5588
  ctv.fit(heart, id_col="id", event_col="event", strata=["transplant"], initial_point=0.1 * np.ones(3))
5589
5589
  npt.assert_allclose(ctv.log_likelihood_ratio_test().test_statistic, 15.68, atol=0.01)
5590
5590
 
5591
- def test_fitter_is_okay_with_trival_df(self, ctv):
5591
+ def test_fitter_is_okay_with_trivial_df(self, ctv):
5592
5592
  # after all the necessary columns are removed, does this fitter still work with a trivial df?
5593
5593
  df = pd.DataFrame.from_records(
5594
5594
  [
@@ -360,12 +360,12 @@ class TestPlotting:
360
360
  self.plt.show(block=block)
361
361
  return
362
362
 
363
- def test_naf_plot_cumulative_hazard_bandwith_1(self, block):
363
+ def test_naf_plot_cumulative_hazard_bandwidth_1(self, block):
364
364
  data1 = np.random.exponential(5, size=(2000, 1)) ** 2
365
365
  naf = NelsonAalenFitter()
366
366
  naf.fit(data1)
367
367
  naf.plot_hazard(bandwidth=5.0, iloc=slice(0, 1700))
368
- self.plt.title("test_naf_plot_cumulative_hazard_bandwith_1")
368
+ self.plt.title("test_naf_plot_cumulative_hazard_bandwidth_1")
369
369
  self.plt.show(block=block)
370
370
  return
371
371
 
@@ -347,7 +347,7 @@ def test_survival_table_from_events_at_risk_column():
347
347
  1.0,
348
348
  ]
349
349
  df = utils.survival_table_from_events(df["T"], df["E"])
350
- assert list(df["at_risk"][1:]) == expected # skip the first event as that is the birth time, 0.
350
+ assert list(df["at_risk"].loc[1:]) == expected # skip the first event as that is the birth time, 0.
351
351
 
352
352
 
353
353
  def test_survival_table_to_events_casts_to_float():
@@ -11,7 +11,7 @@ import warnings
11
11
  from numpy import ndarray
12
12
  import numpy as np
13
13
 
14
- from scipy.integrate import quad, trapz
14
+ from scipy.integrate import quad, trapezoid
15
15
  from scipy.linalg import solve
16
16
  from scipy import stats
17
17
 
@@ -266,7 +266,7 @@ def _expected_value_of_survival_up_to_t(model_or_survival_function, t: float = n
266
266
  )
267
267
  sf = model_or_survival_function.loc[:t]
268
268
  sf = pd.concat((sf, pd.DataFrame([1], index=[0], columns=sf.columns))).sort_index()
269
- return trapz(y=sf.values[:, 0], x=sf.index)
269
+ return trapezoid(y=sf.values[:, 0], x=sf.index)
270
270
  elif isinstance(model_or_survival_function, lifelines.fitters.UnivariateFitter):
271
271
  # lifelines model
272
272
  model = model_or_survival_function
@@ -313,7 +313,7 @@ def _expected_value_of_survival_squared_up_to_t(
313
313
  sf = model_or_survival_function.loc[:t]
314
314
  sf = pd.concat((sf, pd.DataFrame([1], index=[0], columns=sf.columns))).sort_index()
315
315
  sf_tau = sf * sf.index.values[:, None]
316
- return 2 * trapz(y=sf_tau.values[:, 0], x=sf_tau.index)
316
+ return 2 * trapezoid(y=sf_tau.values[:, 0], x=sf_tau.index)
317
317
  elif isinstance(model_or_survival_function, lifelines.fitters.UnivariateFitter):
318
318
  # lifelines model
319
319
  model = model_or_survival_function
@@ -556,7 +556,7 @@ def _group_event_table_by_intervals(event_table, intervals) -> pd.DataFrame:
556
556
 
557
557
  intervals = np.arange(0, event_max + bin_width, bin_width)
558
558
 
559
- event_table = event_table.groupby(pd.cut(event_table["event_at"], intervals, include_lowest=True)).agg(
559
+ event_table = event_table.groupby(pd.cut(event_table["event_at"], intervals, include_lowest=True), observed=False).agg(
560
560
  {"removed": ["sum"], "observed": ["sum"], "censored": ["sum"], "at_risk": ["max"]}
561
561
  )
562
562
  # convert columns from multiindex
@@ -648,7 +648,7 @@ def datetimes_to_durations(
648
648
  the units of time to use. See Pandas 'freq'. Default 'D' for days.
649
649
  dayfirst: bool, optional (default=False)
650
650
  see Pandas `to_datetime`
651
- na_values : list, optional
651
+ na_values : list[str], optional
652
652
  list of values to recognize as NA/NaN. Ex: ['', 'NaT']
653
653
  format:
654
654
  see Pandas `to_datetime`
@@ -679,7 +679,7 @@ def datetimes_to_durations(
679
679
  start_times = pd.Series(start_times).copy()
680
680
  end_times = pd.Series(end_times).copy()
681
681
 
682
- C = ~(pd.isnull(end_times).values | end_times.isin(na_values or [""]))
682
+ C = ~(pd.isnull(end_times).values | end_times.astype(str).isin(na_values or [""]))
683
683
  end_times[~C] = fill_date_
684
684
  start_times_ = pd.to_datetime(start_times, dayfirst=dayfirst, format=format)
685
685
  end_times_ = pd.to_datetime(end_times, dayfirst=dayfirst, errors="coerce", format=format)
@@ -1464,7 +1464,7 @@ def add_covariate_to_timeline(
1464
1464
  cv = cv.sort_values([id_col, duration_col])
1465
1465
  cvs = cv.pipe(remove_redundant_rows).pipe(transform_cv_to_long_format).groupby(id_col, sort=True)
1466
1466
 
1467
- long_form_df = long_form_df.groupby(id_col, group_keys=False, sort=True).apply(expand, cvs=cvs)
1467
+ long_form_df = long_form_df.groupby(id_col, group_keys=False, sort=True)[long_form_df.columns].apply(expand, cvs=cvs)
1468
1468
  return long_form_df.reset_index(drop=True)
1469
1469
 
1470
1470
 
@@ -1506,7 +1506,7 @@ def covariates_from_event_matrix(df, id_col) -> pd.DataFrame:
1506
1506
  """
1507
1507
  df = df.set_index(id_col)
1508
1508
  df = df.fillna(np.inf)
1509
- df = df.stack(dropna=False).reset_index()
1509
+ df = df.stack(future_stack=True).reset_index()
1510
1510
  df.columns = [id_col, "event", "duration"]
1511
1511
  df["_counter"] = 1
1512
1512
  return (
@@ -1,4 +1,4 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  from __future__ import unicode_literals
3
3
 
4
- __version__ = "0.28.0"
4
+ __version__ = "0.29.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lifelines
3
- Version: 0.28.0
3
+ Version: 0.29.0
4
4
  Summary: Survival analysis in Python, including Kaplan Meier, Nelson Aalen and regression
5
5
  Home-page: https://github.com/CamDavidsonPilon/lifelines
6
6
  Author: Cameron Davidson-Pilon
@@ -17,8 +17,8 @@ Requires-Python: >=3.9
17
17
  Description-Content-Type: text/markdown
18
18
  License-File: LICENSE
19
19
  Requires-Dist: numpy<2.0,>=1.14.0
20
- Requires-Dist: scipy>=1.2.0
21
- Requires-Dist: pandas>=1.2.0
20
+ Requires-Dist: scipy>=1.7.0
21
+ Requires-Dist: pandas>=2.1
22
22
  Requires-Dist: matplotlib>=3.0
23
23
  Requires-Dist: autograd>=1.5
24
24
  Requires-Dist: autograd-gamma>=0.3
@@ -50,8 +50,8 @@ If you are new to survival analysis, wondering why it is useful, or are interest
50
50
 
51
51
  ## Contact
52
52
  - Start a conversation in our [Discussions room](https://github.com/CamDavidsonPilon/lifelines/discussions).
53
- - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion)
54
- - creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
53
+ - Some users have posted common questions at [stats.stackexchange.com](https://stats.stackexchange.com/search?tab=votes&q=%22lifelines%22%20is%3aquestion).
54
+ - Creating an issue in the [Github repository](https://github.com/camdavidsonpilon/lifelines).
55
55
 
56
56
  ## Development
57
57
 
@@ -1,6 +1,6 @@
1
1
  numpy<2.0,>=1.14.0
2
- scipy>=1.2.0
3
- pandas>=1.2.0
2
+ scipy>=1.7.0
3
+ pandas>=2.1
4
4
  matplotlib>=3.0
5
5
  autograd>=1.5
6
6
  autograd-gamma>=0.3
@@ -1,6 +1,6 @@
1
1
  numpy>=1.14.0,<2.0
2
- scipy>=1.2.0
3
- pandas>=1.2.0
2
+ scipy>=1.7.0
3
+ pandas>=2.1
4
4
  matplotlib>=3.0
5
5
  autograd>=1.5
6
6
  autograd-gamma>=0.3
@@ -15,8 +15,8 @@ black
15
15
  dill>=0.3.6
16
16
  statsmodels
17
17
  flaky
18
- scikit-learn>=0.22.0
19
18
  Jinja2
19
+ joblib
20
20
 
21
21
  # ex: `py.test` in the docs/ folder. See conftest.py in docs/ first
22
22
  sybil
File without changes
File without changes
File without changes
File without changes