death-pred 0.1.0__py3-none-any.whl
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.
- death_pred/__init__.py +3 -0
- death_pred/__main__.py +45 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/__init__.py +0 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/base/__init__.py +0 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/base/table.py +356 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/config/__init__.py +0 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/config/spark.py +294 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/config/utils.py +228 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/Customize_with_known_ids.py +6 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/__init__.py +0 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/cohort_generation_with_known_ids.py +148 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/cohort_select.py +221 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/ehr_generation_common.py +276 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/ehr_generation_no_meds_with_known_ids.py +50 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/ehr_generation_no_meds_with_known_ids_chunks.py +50 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/merge.py +109 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/modalities.py +421 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/model_predict_external_validation.py +207 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/predictor_extractor.py +297 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/scd_death_classification.py +246 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/scd_reclassification.py +546 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/summarise_results_for_export.py +288 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/CPRD/functions/tables.py +281 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/README_external_validation.md +1124 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/VENDORED.txt +23 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/__init__.py +25 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/config.py +225 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/__init__.py +38 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/datasets.py +360 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/masking.py +225 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/tokenization.py +146 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/ttd.py +108 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/data/vocabulary.py +238 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/model/__init__.py +10 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/model/bert.py +345 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/model/embeddings.py +241 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/model/heads.py +240 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/model/layers.py +279 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/utils/__init__.py +5 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/behrt/utils/io.py +95 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/config/config.yaml +14 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/config/model_config.json +22 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/reference/SCD_exclusion_codes.txt +1 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/reference/SCD_inclusion_codes.txt +1 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/requirements.txt +15 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/utils/utils.py +19 -0
- death_pred/bundle/BEHRT_external_validation_polars_p312/utils/yaml_act.py +19 -0
- death_pred/bundle/SCD/models/model_dx_only_chained_seed88.bin +0 -0
- death_pred/bundle/SCD/models/model_dx_proc_chained_seed62.bin +0 -0
- death_pred/bundle/SCD/tables/GeneralVocDMProc_25k_tabextrav2.pkl +0 -0
- death_pred/bundle/SCD/tables/GeneralVocDMProc_25k_tabextrav2.txt +8349 -0
- death_pred/bundle/SCD/tables/OPCS4_to_SKS_final_mapping.csv +7203 -0
- death_pred/bundle/SCD/tables/icd10_opcs4_codes.txt +3484 -0
- death_pred-0.1.0.dist-info/METADATA +15 -0
- death_pred-0.1.0.dist-info/RECORD +57 -0
- death_pred-0.1.0.dist-info/WHEEL +4 -0
- death_pred-0.1.0.dist-info/entry_points.txt +2 -0
death_pred/__init__.py
ADDED
death_pred/__main__.py
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Unpack the codes into a folder of your choice.
|
|
2
|
+
|
|
3
|
+
death-pred-unpack <YOUR_BASE_PATH>
|
|
4
|
+
python -m death_pred <YOUR_BASE_PATH>
|
|
5
|
+
"""
|
|
6
|
+
import argparse
|
|
7
|
+
import shutil
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
BUNDLE = Path(__file__).resolve().parent / "bundle"
|
|
12
|
+
FOLDERS = ["BEHRT_external_validation_polars_p312", "SCD"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def main(argv=None):
|
|
16
|
+
parser = argparse.ArgumentParser(
|
|
17
|
+
prog="death-pred-unpack",
|
|
18
|
+
description="Copy the code and model folders into BASE_PATH.",
|
|
19
|
+
)
|
|
20
|
+
parser.add_argument("base_path", nargs="?", default=".",
|
|
21
|
+
help="folder to unpack into (created if missing; default: current folder)")
|
|
22
|
+
args = parser.parse_args(argv)
|
|
23
|
+
|
|
24
|
+
base = Path(args.base_path).expanduser().resolve()
|
|
25
|
+
existing = [str(base / name) for name in FOLDERS if (base / name).exists()]
|
|
26
|
+
if existing:
|
|
27
|
+
sys.exit("Not unpacking, because these already exist and would be overwritten:\n "
|
|
28
|
+
+ "\n ".join(existing)
|
|
29
|
+
+ "\nChoose another folder, or move them out of the way first.")
|
|
30
|
+
|
|
31
|
+
base.mkdir(parents=True, exist_ok=True)
|
|
32
|
+
for name in FOLDERS:
|
|
33
|
+
# pip compiles the installed scripts; its cache folders are not part of the bundle.
|
|
34
|
+
shutil.copytree(BUNDLE / name, base / name,
|
|
35
|
+
ignore=shutil.ignore_patterns("__pycache__", "*.pyc"))
|
|
36
|
+
(base / "SCD" / "predictions").mkdir(exist_ok=True)
|
|
37
|
+
|
|
38
|
+
readme = base / "BEHRT_external_validation_polars_p312" / "README_external_validation.md"
|
|
39
|
+
print(f"Unpacked into {base}\n"
|
|
40
|
+
f"Next: open {readme}, read 'What may leave this server', then follow it from section 3.\n"
|
|
41
|
+
"(The Python dependencies were installed by pip, so sections 1 and 2 are already done.)")
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
if __name__ == "__main__":
|
|
45
|
+
main()
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import polars as pl
|
|
2
|
+
from CPRD.config.utils import cvt_str2time, cvt_datestr2time
|
|
3
|
+
from utils.utils import *
|
|
4
|
+
|
|
5
|
+
try:
|
|
6
|
+
DICT2KEEP = load_obj('/path/linkage_coverage_dictv')
|
|
7
|
+
except Exception:
|
|
8
|
+
DICT2KEEP = {
|
|
9
|
+
'ons_death': ('01/01/1900', '01/01/2100')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class _TableBase:
|
|
14
|
+
"""Base class wrapping a Polars DataFrame. Processing methods return new
|
|
15
|
+
instances so that the original chaining pattern is preserved."""
|
|
16
|
+
|
|
17
|
+
def __init__(self, df):
|
|
18
|
+
if isinstance(df, _TableBase):
|
|
19
|
+
self._df = df._df
|
|
20
|
+
elif isinstance(df, pl.DataFrame):
|
|
21
|
+
self._df = df
|
|
22
|
+
else:
|
|
23
|
+
raise TypeError(f"Expected pl.DataFrame or _TableBase, got {type(df)}")
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def df(self):
|
|
27
|
+
"""Access the underlying Polars DataFrame."""
|
|
28
|
+
return self._df
|
|
29
|
+
|
|
30
|
+
@property
|
|
31
|
+
def columns(self):
|
|
32
|
+
return self._df.columns
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def height(self):
|
|
36
|
+
return self._df.height
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def schema(self):
|
|
40
|
+
return self._df.schema
|
|
41
|
+
|
|
42
|
+
def __len__(self):
|
|
43
|
+
return self._df.height
|
|
44
|
+
|
|
45
|
+
def __repr__(self):
|
|
46
|
+
return f"{self.__class__.__name__}({self._df.__repr__()})"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# ---------------------------------------------------------------------------
|
|
50
|
+
# Patient
|
|
51
|
+
# ---------------------------------------------------------------------------
|
|
52
|
+
class Patient(_TableBase):
|
|
53
|
+
def __init__(self, df):
|
|
54
|
+
super().__init__(df)
|
|
55
|
+
|
|
56
|
+
def accept_flag(self):
|
|
57
|
+
return Patient(self._df.filter(pl.col('acceptable') == 1))
|
|
58
|
+
|
|
59
|
+
def yob_calibration(self):
|
|
60
|
+
return Patient(self._df.with_columns(pl.col('yob').cast(pl.Int32)))
|
|
61
|
+
|
|
62
|
+
def cvt_tod2date(self):
|
|
63
|
+
return Patient(
|
|
64
|
+
self._df.with_columns(
|
|
65
|
+
cvt_datestr2time(self._df, 'regenddate').alias('tod')
|
|
66
|
+
).drop('regenddate')
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
def cvt_deathdate2date(self):
|
|
70
|
+
return Patient(
|
|
71
|
+
self._df.with_columns(
|
|
72
|
+
cvt_datestr2time(self._df, 'cprd_ddate').alias('cprd_ddate')
|
|
73
|
+
)
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
def cvt_crd2date(self):
|
|
77
|
+
return Patient(
|
|
78
|
+
self._df.with_columns(
|
|
79
|
+
cvt_datestr2time(self._df, 'regstartdate').alias('crd')
|
|
80
|
+
).drop('regstartdate')
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
def cvt_pracid(self):
|
|
84
|
+
return Patient(self._df.with_columns(pl.col('pracid').cast(pl.Int32)))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
# ---------------------------------------------------------------------------
|
|
88
|
+
# Clinical
|
|
89
|
+
# ---------------------------------------------------------------------------
|
|
90
|
+
class Clinical(_TableBase):
|
|
91
|
+
def __init__(self, df):
|
|
92
|
+
super().__init__(df)
|
|
93
|
+
|
|
94
|
+
def cvtEventDate2Time(self):
|
|
95
|
+
return Clinical(
|
|
96
|
+
self._df.with_columns(
|
|
97
|
+
cvt_datestr2time(self._df, 'obsdate').alias('eventdate')
|
|
98
|
+
).drop('obsdate')
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def rm_eventdate_medcode_empty(self):
|
|
102
|
+
return Clinical(
|
|
103
|
+
self._df.filter(
|
|
104
|
+
(pl.col('obsdate') != '') & (pl.col('medcodeid') != '')
|
|
105
|
+
).rename({'medcodeid': 'medcode'})
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
def filter_byobservation(self):
|
|
109
|
+
return Clinical(self._df.filter(pl.col('obstypeid') == '7'))
|
|
110
|
+
|
|
111
|
+
def filter_byid(self, id_str):
|
|
112
|
+
return Clinical(self._df.filter(pl.col('obstypeid') == id_str))
|
|
113
|
+
|
|
114
|
+
def filter_byidlist(self, id_str):
|
|
115
|
+
return Clinical(self._df.filter(pl.col('obstypeid').is_in(id_str)))
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
# ---------------------------------------------------------------------------
|
|
119
|
+
# Consultation
|
|
120
|
+
# ---------------------------------------------------------------------------
|
|
121
|
+
class Consultation(_TableBase):
|
|
122
|
+
def __init__(self, df):
|
|
123
|
+
super().__init__(df)
|
|
124
|
+
|
|
125
|
+
def cvtEventDate2Time(self):
|
|
126
|
+
return Consultation(
|
|
127
|
+
self._df.with_columns(
|
|
128
|
+
cvt_datestr2time(self._df, 'consdate').alias('eventdate')
|
|
129
|
+
).drop('consdate')
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
def rm_eventdate_medcode_empty(self):
|
|
133
|
+
return Consultation(
|
|
134
|
+
self._df.filter(
|
|
135
|
+
(pl.col('consdate') != '') & (pl.col('consmedcodeid') != '')
|
|
136
|
+
).with_columns(
|
|
137
|
+
pl.col('consmedcodeid').alias('medcode')
|
|
138
|
+
).drop('consmedcodeid')
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
# ---------------------------------------------------------------------------
|
|
143
|
+
# Practice
|
|
144
|
+
# ---------------------------------------------------------------------------
|
|
145
|
+
class Practice(_TableBase):
|
|
146
|
+
def __init__(self, df):
|
|
147
|
+
super().__init__(df)
|
|
148
|
+
|
|
149
|
+
def cvt_lcd2date(self):
|
|
150
|
+
return Practice(
|
|
151
|
+
self._df.with_columns(
|
|
152
|
+
cvt_datestr2time(self._df, 'lcd').alias('lcd')
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
def cvt_uts2date(self):
|
|
157
|
+
return Practice(
|
|
158
|
+
self._df.drop('uts').with_columns(
|
|
159
|
+
pl.lit(None).cast(pl.Date).alias('uts')
|
|
160
|
+
)
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
def intpracid(self):
|
|
164
|
+
return Practice(self._df.with_columns(pl.col('pracid').cast(pl.Int32)))
|
|
165
|
+
|
|
166
|
+
def rmv_badPract(self):
|
|
167
|
+
badlist = []
|
|
168
|
+
if badlist:
|
|
169
|
+
return Practice(self._df.filter(~pl.col('pracid').is_in(badlist)))
|
|
170
|
+
return self
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
# ---------------------------------------------------------------------------
|
|
174
|
+
# Diagnosis
|
|
175
|
+
# ---------------------------------------------------------------------------
|
|
176
|
+
class Diagnosis(_TableBase):
|
|
177
|
+
def __init__(self, df):
|
|
178
|
+
super().__init__(df)
|
|
179
|
+
|
|
180
|
+
def cvt_admidate2date(self):
|
|
181
|
+
return Diagnosis(
|
|
182
|
+
self._df.with_columns(
|
|
183
|
+
cvt_datestr2time(self._df, 'admidate').alias('admidate')
|
|
184
|
+
)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
def icd_rm_dot(self):
|
|
188
|
+
return Diagnosis(
|
|
189
|
+
self._df.with_columns(
|
|
190
|
+
pl.col('ICD').str.replace_all(r"\.", "")
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
|
|
194
|
+
def rm_date_icd_empty(self):
|
|
195
|
+
return Diagnosis(
|
|
196
|
+
self._df.filter((pl.col('admidate') != '') & (pl.col('ICD') != ''))
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
def hes_apc_timefilter(self):
|
|
200
|
+
if 'hes_apc' not in DICT2KEEP:
|
|
201
|
+
return self
|
|
202
|
+
goodstart = pl.lit(DICT2KEEP['hes_apc'][0]).str.to_date("dd/MM/yyyy", strict=False)
|
|
203
|
+
goodend = pl.lit(DICT2KEEP['hes_apc'][1]).str.to_date("dd/MM/yyyy", strict=False)
|
|
204
|
+
return Diagnosis(
|
|
205
|
+
self._df.filter(
|
|
206
|
+
(pl.col('admidate') >= goodstart) & (pl.col('admidate') < goodend)
|
|
207
|
+
)
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
# ---------------------------------------------------------------------------
|
|
212
|
+
# Hes
|
|
213
|
+
# ---------------------------------------------------------------------------
|
|
214
|
+
class Hes(_TableBase):
|
|
215
|
+
def __init__(self, df):
|
|
216
|
+
super().__init__(df)
|
|
217
|
+
|
|
218
|
+
def cvt_string2date(self, col):
|
|
219
|
+
# Rearrange dd/MM/yyyy to yyyyMMdd, then parse
|
|
220
|
+
df = self._df.with_columns(
|
|
221
|
+
pl.concat_str([
|
|
222
|
+
pl.col(col).str.slice(6, 4),
|
|
223
|
+
pl.col(col).str.slice(3, 2),
|
|
224
|
+
pl.col(col).str.slice(0, 2),
|
|
225
|
+
]).str.to_date("%Y%m%d", strict=False).alias(col)
|
|
226
|
+
)
|
|
227
|
+
return Hes(df)
|
|
228
|
+
|
|
229
|
+
def rm_dot(self, col):
|
|
230
|
+
return Hes(
|
|
231
|
+
self._df.with_columns(
|
|
232
|
+
pl.col(col).str.replace_all(r"\.", "")
|
|
233
|
+
)
|
|
234
|
+
)
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
# ---------------------------------------------------------------------------
|
|
238
|
+
# Therapy
|
|
239
|
+
# ---------------------------------------------------------------------------
|
|
240
|
+
class Therapy(_TableBase):
|
|
241
|
+
def __init__(self, df):
|
|
242
|
+
super().__init__(df)
|
|
243
|
+
|
|
244
|
+
def rm_eventdate_prodcode_empty(self):
|
|
245
|
+
return Therapy(
|
|
246
|
+
self._df.filter(
|
|
247
|
+
(pl.col('issuedate') != '') & (pl.col('prodcodeid') != '')
|
|
248
|
+
).rename({'prodcodeid': 'prodcode', 'issuedate': 'eventdate'})
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def cvtEventDate2Time(self):
|
|
252
|
+
return Therapy(
|
|
253
|
+
self._df.with_columns(
|
|
254
|
+
cvt_datestr2time(self._df, 'eventdate').alias('eventdate')
|
|
255
|
+
)
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
# ---------------------------------------------------------------------------
|
|
260
|
+
# EHR (used by predictor_extractor for sequence building)
|
|
261
|
+
# ---------------------------------------------------------------------------
|
|
262
|
+
class EHR(_TableBase):
|
|
263
|
+
def __init__(self, df):
|
|
264
|
+
super().__init__(df)
|
|
265
|
+
|
|
266
|
+
def cal_age(self, event_date, yob, year=True, name='age'):
|
|
267
|
+
"""Calculate age from event_date and yob (both Date columns)."""
|
|
268
|
+
if year:
|
|
269
|
+
df = self._df.with_columns(
|
|
270
|
+
(pl.col(event_date).dt.year() - pl.col(yob).dt.year()).alias(name)
|
|
271
|
+
)
|
|
272
|
+
else:
|
|
273
|
+
# Age in months; assume born in January
|
|
274
|
+
df = self._df.with_columns(
|
|
275
|
+
(
|
|
276
|
+
(pl.col(event_date).dt.year() * 12 + pl.col(event_date).dt.month())
|
|
277
|
+
- (pl.col(yob).dt.year() * 12 + 1)
|
|
278
|
+
).alias(name)
|
|
279
|
+
)
|
|
280
|
+
return EHR(df)
|
|
281
|
+
|
|
282
|
+
def cal_year(self, event_date, name='year'):
|
|
283
|
+
return EHR(
|
|
284
|
+
self._df.with_columns(
|
|
285
|
+
pl.col(event_date).dt.year().alias(name)
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
def set_col_to_str(self, col):
|
|
290
|
+
return EHR(self._df.with_columns(pl.col(col).cast(pl.Utf8)))
|
|
291
|
+
|
|
292
|
+
def array_add_element(self, col, element):
|
|
293
|
+
"""Append a single element to each list in a List[Utf8] column."""
|
|
294
|
+
dtype = self._df.schema[col]
|
|
295
|
+
inner = dtype.inner if isinstance(dtype, pl.List) else pl.Utf8
|
|
296
|
+
return EHR(
|
|
297
|
+
self._df.with_columns(
|
|
298
|
+
pl.col(col).map_elements(
|
|
299
|
+
lambda lst: list(lst) + [element],
|
|
300
|
+
return_dtype=pl.List(inner),
|
|
301
|
+
)
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
def array_flatten(self, col):
|
|
306
|
+
"""Flatten a List[List[T]] column into List[T]."""
|
|
307
|
+
dtype = self._df.schema[col]
|
|
308
|
+
if isinstance(dtype, pl.List) and isinstance(dtype.inner, pl.List):
|
|
309
|
+
inner_type = dtype.inner.inner
|
|
310
|
+
return EHR(
|
|
311
|
+
self._df.with_columns(
|
|
312
|
+
pl.col(col).map_elements(
|
|
313
|
+
lambda lst: [item for sublist in lst for item in sublist],
|
|
314
|
+
return_dtype=pl.List(inner_type),
|
|
315
|
+
)
|
|
316
|
+
)
|
|
317
|
+
)
|
|
318
|
+
return self
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
# ---------------------------------------------------------------------------
|
|
322
|
+
# Proc_HES
|
|
323
|
+
# ---------------------------------------------------------------------------
|
|
324
|
+
class Proc_HES(_TableBase):
|
|
325
|
+
def __init__(self, df):
|
|
326
|
+
super().__init__(df)
|
|
327
|
+
|
|
328
|
+
def cvt_admidate2date(self):
|
|
329
|
+
return Proc_HES(
|
|
330
|
+
self._df.with_columns(
|
|
331
|
+
cvt_datestr2time(self._df, 'evdate').alias('evdate')
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
def icd_rm_dot(self):
|
|
336
|
+
return Proc_HES(
|
|
337
|
+
self._df.with_columns(
|
|
338
|
+
pl.col('ICD').str.replace_all(r"\.", "")
|
|
339
|
+
)
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
def rm_date_opcs_empty(self):
|
|
343
|
+
return Proc_HES(
|
|
344
|
+
self._df.filter((pl.col('evdate') != '') & (pl.col('OPCS') != ''))
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
def hes_apc_timefilter(self):
|
|
348
|
+
if 'hes_apc' not in DICT2KEEP:
|
|
349
|
+
return self
|
|
350
|
+
goodstart = pl.lit(DICT2KEEP['hes_apc'][0]).str.to_date("dd/MM/yyyy", strict=False)
|
|
351
|
+
goodend = pl.lit(DICT2KEEP['hes_apc'][1]).str.to_date("dd/MM/yyyy", strict=False)
|
|
352
|
+
return Proc_HES(
|
|
353
|
+
self._df.filter(
|
|
354
|
+
(pl.col('evdate') >= goodstart) & (pl.col('evdate') < goodend)
|
|
355
|
+
)
|
|
356
|
+
)
|
|
File without changes
|