Combine populations for weighted mRS distributions#
Use the patient population to combine the mRS distributions from the separate cohorts.
Plain English summary#
In the previous notebook we calculated outcomes for patients across all of England and Wales. This assumed fixed times to treatment except for travel times to the stroke units. We calculated one set of times for the drip-and-ship scenario, where patients first go to their nearest stroke unit and are later transferred to the MT unit if they need thrombectomy, and a second set of times for the mothership scenario, where every patient goes directly to the MT unit.
The existing data has separate entries for each cohort of patients:
patients with an nLVO treated with IVT
patients with a LVO treated with IVT only
patients with a LVO treated with MT only
patients with a LVO treated with both IVT and MT
In this notebook we will combine the data of multiple groups of patients.
We will then combine all patients around England and Wales to create one set of mRS distributions that applies nationally.
Aims#
To find the averaged mRS distributions after treatment for the following groups:
patients with a LVO and a mix of the available treatment types
patients with an nLVO and patients with a LVO and a mix of the available treatment types
Then to combine the mRS distributions for any LSOA where redirection affects which stroke unit is attended first.
Method#
Use the example patient proportions to calculate a weighted sum of the separate cohorts.
The national mRS distribution uses a weighted combination of the mRS distributions of all LSOAs where redirection affects which stroke unit is attended first. The weights are the predicted number of admissions from each LSOA as calculated in a previous notebook.
Notebook setup#
import pandas as pd
import numpy as np
import os
import stroke_outcome.outcome_utilities
dir_output = 'output'
Import data#
Patient proportions:
proportions = pd.read_csv(
os.path.join(dir_output, 'patient_proportions.csv'),
index_col=0, header=None).squeeze()
proportions
0
haemorrhagic 0.13600
lvo_no_treatment 0.14648
lvo_ivt_only 0.00840
lvo_ivt_mt 0.08500
lvo_mt_only 0.01500
nlvo_no_treatment 0.50252
nlvo_ivt 0.10660
Name: 1, dtype: float64
Calculate some additional proportions:
# Proportion of treated LVO patients:
prop_lvo_treated = 0.0
for key, value in proportions.items():
if (('lvo' in key) & ('nlvo' not in key) & ('no_treat' not in key)):
print(key)
prop_lvo_treated += value
prop_lvo_treated
lvo_ivt_only
lvo_ivt_mt
lvo_mt_only
0.10840000000000001
# Proportion of treated ischaemic patients:
prop_ischaemic_treated = 0.0
for key, value in proportions.items():
if (('lvo' in key) & ('no_treat' not in key)):
print(key)
prop_ischaemic_treated += value
prop_ischaemic_treated
lvo_ivt_only
lvo_ivt_mt
lvo_mt_only
nlvo_ivt
0.21500000000000002
# Proportion of ischaemic patients:
prop_ischaemic = 1.0 - proportions['haemorrhagic']
prop_ischaemic
0.864
mRS distributions:
df_mrs = pd.read_csv(os.path.join(dir_output, 'cohort_mrs_dists.csv'), index_col=0)
df_mrs.info()
<class 'pandas.core.frame.DataFrame'>
Index: 34752 entries, Adur 001A to York 024F
Data columns (total 67 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 closest_ivt_time 34752 non-null float64
1 closest_ivt_unit 34752 non-null object
2 closest_mt_time 34752 non-null float64
3 closest_mt_unit 34752 non-null object
4 transfer_mt_time 34752 non-null float64
5 transfer_mt_unit 34752 non-null object
6 mt_transfer_required 34752 non-null bool
7 ivt_drip_ship 34752 non-null float64
8 mt_drip_ship 34752 non-null float64
9 ivt_mothership 34752 non-null float64
10 mt_mothership 34752 non-null float64
11 drip_ship_nlvo_ivt_mrs_dists_0 34752 non-null float64
12 drip_ship_nlvo_ivt_mrs_dists_1 34752 non-null float64
13 drip_ship_nlvo_ivt_mrs_dists_2 34752 non-null float64
14 drip_ship_nlvo_ivt_mrs_dists_3 34752 non-null float64
15 drip_ship_nlvo_ivt_mrs_dists_4 34752 non-null float64
16 drip_ship_nlvo_ivt_mrs_dists_5 34752 non-null float64
17 drip_ship_nlvo_ivt_mrs_dists_6 34752 non-null float64
18 drip_ship_lvo_ivt_mrs_dists_0 34752 non-null float64
19 drip_ship_lvo_ivt_mrs_dists_1 34752 non-null float64
20 drip_ship_lvo_ivt_mrs_dists_2 34752 non-null float64
21 drip_ship_lvo_ivt_mrs_dists_3 34752 non-null float64
22 drip_ship_lvo_ivt_mrs_dists_4 34752 non-null float64
23 drip_ship_lvo_ivt_mrs_dists_5 34752 non-null float64
24 drip_ship_lvo_ivt_mrs_dists_6 34752 non-null float64
25 drip_ship_lvo_ivt_mt_mrs_dists_0 34752 non-null float64
26 drip_ship_lvo_ivt_mt_mrs_dists_1 34752 non-null float64
27 drip_ship_lvo_ivt_mt_mrs_dists_2 34752 non-null float64
28 drip_ship_lvo_ivt_mt_mrs_dists_3 34752 non-null float64
29 drip_ship_lvo_ivt_mt_mrs_dists_4 34752 non-null float64
30 drip_ship_lvo_ivt_mt_mrs_dists_5 34752 non-null float64
31 drip_ship_lvo_ivt_mt_mrs_dists_6 34752 non-null float64
32 drip_ship_lvo_mt_mrs_dists_0 34752 non-null float64
33 drip_ship_lvo_mt_mrs_dists_1 34752 non-null float64
34 drip_ship_lvo_mt_mrs_dists_2 34752 non-null float64
35 drip_ship_lvo_mt_mrs_dists_3 34752 non-null float64
36 drip_ship_lvo_mt_mrs_dists_4 34752 non-null float64
37 drip_ship_lvo_mt_mrs_dists_5 34752 non-null float64
38 drip_ship_lvo_mt_mrs_dists_6 34752 non-null float64
39 mothership_nlvo_ivt_mrs_dists_0 34752 non-null float64
40 mothership_nlvo_ivt_mrs_dists_1 34752 non-null float64
41 mothership_nlvo_ivt_mrs_dists_2 34752 non-null float64
42 mothership_nlvo_ivt_mrs_dists_3 34752 non-null float64
43 mothership_nlvo_ivt_mrs_dists_4 34752 non-null float64
44 mothership_nlvo_ivt_mrs_dists_5 34752 non-null float64
45 mothership_nlvo_ivt_mrs_dists_6 34752 non-null float64
46 mothership_lvo_ivt_mrs_dists_0 34752 non-null float64
47 mothership_lvo_ivt_mrs_dists_1 34752 non-null float64
48 mothership_lvo_ivt_mrs_dists_2 34752 non-null float64
49 mothership_lvo_ivt_mrs_dists_3 34752 non-null float64
50 mothership_lvo_ivt_mrs_dists_4 34752 non-null float64
51 mothership_lvo_ivt_mrs_dists_5 34752 non-null float64
52 mothership_lvo_ivt_mrs_dists_6 34752 non-null float64
53 mothership_lvo_ivt_mt_mrs_dists_0 34752 non-null float64
54 mothership_lvo_ivt_mt_mrs_dists_1 34752 non-null float64
55 mothership_lvo_ivt_mt_mrs_dists_2 34752 non-null float64
56 mothership_lvo_ivt_mt_mrs_dists_3 34752 non-null float64
57 mothership_lvo_ivt_mt_mrs_dists_4 34752 non-null float64
58 mothership_lvo_ivt_mt_mrs_dists_5 34752 non-null float64
59 mothership_lvo_ivt_mt_mrs_dists_6 34752 non-null float64
60 mothership_lvo_mt_mrs_dists_0 34752 non-null float64
61 mothership_lvo_mt_mrs_dists_1 34752 non-null float64
62 mothership_lvo_mt_mrs_dists_2 34752 non-null float64
63 mothership_lvo_mt_mrs_dists_3 34752 non-null float64
64 mothership_lvo_mt_mrs_dists_4 34752 non-null float64
65 mothership_lvo_mt_mrs_dists_5 34752 non-null float64
66 mothership_lvo_mt_mrs_dists_6 34752 non-null float64
dtypes: bool(1), float64(63), object(3)
memory usage: 17.8+ MB
mRS distributions#
Load in admissions data#
admissions = pd.read_csv('./data/lsoa_predicted_admissions.csv')
admissions.head(3)
lsoa11cd | lsoa11nm | msoa11cd | msoa11nm | country | LSOA_predicted_admissions | |
---|---|---|---|---|---|---|
0 | E01000001 | City of London 001A | E02000001 | City of London 001 | E | 1.569672 |
1 | E01000002 | City of London 001B | E02000001 | City of London 001 | E | 1.569672 |
2 | E01000003 | City of London 001C | E02000001 | City of London 001 | E | 1.569672 |
df_mrs = pd.merge(
df_mrs.reset_index(), admissions[['lsoa11nm', 'LSOA_predicted_admissions']],
left_on='LSOA', right_on='lsoa11nm', how='left'
)
Make non-cumulative mRS distributions#
cols_to_combine = [c for c in df_mrs.columns if 'dist' in c]
# Remove repeats from all the mRS bands:
cols_each_scen = sorted(list(set(['_'.join(c.split('_')[:-1]) for c in cols_to_combine])))
cols_each_scen
['drip_ship_lvo_ivt_mrs_dists',
'drip_ship_lvo_ivt_mt_mrs_dists',
'drip_ship_lvo_mt_mrs_dists',
'drip_ship_nlvo_ivt_mrs_dists',
'mothership_lvo_ivt_mrs_dists',
'mothership_lvo_ivt_mt_mrs_dists',
'mothership_lvo_mt_mrs_dists',
'mothership_nlvo_ivt_mrs_dists']
# Make non-cumulative mRS distributions:
for c in cols_each_scen:
cols_cumsum = [f'{c}_{i}' for i in range(7)]
cols_noncum = [f'{c}_noncum_{i}' for i in range(7)]
new_data = df_mrs[cols_cumsum].copy()
# Take the difference between mRS bands:
new_data = np.diff(new_data, prepend=0.0, axis=1)
# Round the values:
new_data = np.round(new_data, 5)
# Store:
df_mrs[cols_noncum] = new_data
Import reference no-treatment data#
mrs_dists, mrs_dists_notes = (
stroke_outcome.outcome_utilities.import_mrs_dists_from_file())
mrs_dists
mRS<=0 | mRS<=1 | mRS<=2 | mRS<=3 | mRS<=4 | mRS<=5 | mRS<=6 | |
---|---|---|---|---|---|---|---|
Stroke type | |||||||
pre_stroke_nlvo | 0.583 | 0.746 | 0.850 | 0.951 | 0.993 | 1.000 | 1 |
pre_stroke_lvo | 0.408 | 0.552 | 0.672 | 0.838 | 0.956 | 1.000 | 1 |
no_treatment_lvo | 0.050 | 0.129 | 0.265 | 0.429 | 0.676 | 0.811 | 1 |
no_treatment_nlvo | 0.198 | 0.460 | 0.580 | 0.708 | 0.856 | 0.918 | 1 |
no_effect_nlvo_ivt_deaths | 0.196 | 0.455 | 0.574 | 0.701 | 0.847 | 0.908 | 1 |
no_effect_lvo_ivt_deaths | 0.048 | 0.124 | 0.255 | 0.414 | 0.653 | 0.783 | 1 |
no_effect_lvo_mt_deaths | 0.048 | 0.124 | 0.255 | 0.412 | 0.649 | 0.779 | 1 |
t0_treatment_nlvo_ivt | 0.445 | 0.642 | 0.752 | 0.862 | 0.941 | 0.967 | 1 |
t0_treatment_lvo_ivt | 0.140 | 0.233 | 0.361 | 0.522 | 0.730 | 0.838 | 1 |
t0_treatment_lvo_mt | 0.306 | 0.429 | 0.548 | 0.707 | 0.851 | 0.915 | 1 |
mrs_dist_nlvo_no_treatment = mrs_dists.loc['no_treatment_nlvo'].values
mrs_dist_lvo_no_treatment = mrs_dists.loc['no_treatment_lvo'].values
mrs_dist_nlvo_no_treatment_noncum = np.diff(mrs_dist_nlvo_no_treatment, prepend=0.0)
mrs_dist_lvo_no_treatment_noncum = np.diff(mrs_dist_lvo_no_treatment, prepend=0.0)
Combine patient cohorts#
Combine LVO groups:
for model_name in ['drip_ship', 'mothership']:
# New column names for non-cumulative and cumulative probabilities:
cols_noncum = [f'{model_name}_lvo_mix_mrs_dists_noncum_{i}' for i in range(7)]
cols_cum = [f'{model_name}_lvo_mix_mrs_dists_{i}' for i in range(7)]
# Column names of existing data:
cols_lvo_ivt = [f'{model_name}_lvo_ivt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_ivt_mt = [f'{model_name}_lvo_ivt_mt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_mt = [f'{model_name}_lvo_mt_mrs_dists_noncum_{i}' for i in range(7)]
# Weighted sum:
df_mrs[cols_noncum] = (
(df_mrs[cols_lvo_ivt].values * proportions['lvo_ivt_only']) +
(df_mrs[cols_lvo_ivt_mt].values * proportions['lvo_ivt_mt']) +
(df_mrs[cols_lvo_mt].values * proportions['lvo_mt_only'])
)
# Remove the proportion of non-LVO strokes:
df_mrs[cols_noncum] = df_mrs[cols_noncum] / prop_lvo_treated
# Convert to cumulative probabilities:
df_mrs[cols_cum] = np.cumsum(df_mrs[cols_noncum], axis=1)
# Round the results:
df_mrs[cols_noncum] = np.round(df_mrs[cols_noncum], 5)
df_mrs[cols_cum] = np.round(df_mrs[cols_cum], 5)
Weighted treated ischaemic population.
We have no mRS distributions for the haemorrhagic strokes. We calculate the weighted population mRS distributions using the data that we do have, and then divide by the proportion of the population that is not haemorrhagic. This rescales the proportions so that all proportions excluding haemorrhagic sum to 1.
for model_name in ['drip_ship', 'mothership']:
# New column names for non-cumulative and cumulative probabilities:
cols_noncum = [f'{model_name}_weighted_treated_mrs_dists_noncum_{i}' for i in range(7)]
cols_cum = [f'{model_name}_weighted_treated_mrs_dists_{i}' for i in range(7)]
# Column names of existing data:
cols_nlvo_ivt = [f'{model_name}_nlvo_ivt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_ivt = [f'{model_name}_lvo_ivt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_ivt_mt = [f'{model_name}_lvo_ivt_mt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_mt = [f'{model_name}_lvo_mt_mrs_dists_noncum_{i}' for i in range(7)]
# Weighted sum:
df_mrs[cols_noncum] = (
(df_mrs[cols_nlvo_ivt].values * proportions['nlvo_ivt']) +
(df_mrs[cols_lvo_ivt].values * proportions['lvo_ivt_only']) +
(df_mrs[cols_lvo_ivt_mt].values * proportions['lvo_ivt_mt']) +
(df_mrs[cols_lvo_mt].values * proportions['lvo_mt_only'])
)
# Remove the proportion of haemorrhagic strokes:
df_mrs[cols_noncum] = df_mrs[cols_noncum] / prop_ischaemic_treated
# Convert to cumulative probabilities:
df_mrs[cols_cum] = np.cumsum(df_mrs[cols_noncum], axis=1)
# Round the results:
df_mrs[cols_noncum] = np.round(df_mrs[cols_noncum], 5)
df_mrs[cols_cum] = np.round(df_mrs[cols_cum], 5)
Weighted total ischaemic population.
We have no mRS distributions for the haemorrhagic strokes. We calculate the weighted population mRS distributions using the data that we do have, and then divide by the proportion of the population that is not haemorrhagic. This rescales the proportions so that all proportions excluding haemorrhagic sum to 1.
for model_name in ['drip_ship', 'mothership']:
# New column names for non-cumulative and cumulative probabilities:
cols_noncum = [f'{model_name}_weighted_mrs_dists_noncum_{i}' for i in range(7)]
cols_cum = [f'{model_name}_weighted_mrs_dists_{i}' for i in range(7)]
# Column names of existing data:
cols_nlvo_ivt = [f'{model_name}_nlvo_ivt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_ivt = [f'{model_name}_lvo_ivt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_ivt_mt = [f'{model_name}_lvo_ivt_mt_mrs_dists_noncum_{i}' for i in range(7)]
cols_lvo_mt = [f'{model_name}_lvo_mt_mrs_dists_noncum_{i}' for i in range(7)]
# Weighted sum:
df_mrs[cols_noncum] = (
(df_mrs[cols_nlvo_ivt].values * proportions['nlvo_ivt']) +
(df_mrs[cols_lvo_ivt].values * proportions['lvo_ivt_only']) +
(df_mrs[cols_lvo_ivt_mt].values * proportions['lvo_ivt_mt']) +
(df_mrs[cols_lvo_mt].values * proportions['lvo_mt_only']) +
(mrs_dist_nlvo_no_treatment_noncum * proportions['nlvo_no_treatment']) +
(mrs_dist_lvo_no_treatment_noncum * proportions['lvo_no_treatment'])
)
# Remove the proportion of haemorrhagic strokes:
df_mrs[cols_noncum] = df_mrs[cols_noncum] / prop_ischaemic
# Convert to cumulative probabilities:
df_mrs[cols_cum] = np.cumsum(df_mrs[cols_noncum], axis=1)
# Round the results:
df_mrs[cols_noncum] = np.round(df_mrs[cols_noncum], 5)
df_mrs[cols_cum] = np.round(df_mrs[cols_cum], 5)
Average mRS distributions by admissions#
# Remove repeats from all the mRS bands:
cols_each_scen = sorted(list(set(
[c.split('mrs_dist')[0] + 'mrs_dist' for c in df_mrs.columns if 'mrs_dist' in c]
)))
cols_each_scen
['drip_ship_lvo_ivt_mrs_dist',
'drip_ship_lvo_ivt_mt_mrs_dist',
'drip_ship_lvo_mix_mrs_dist',
'drip_ship_lvo_mt_mrs_dist',
'drip_ship_nlvo_ivt_mrs_dist',
'drip_ship_weighted_mrs_dist',
'drip_ship_weighted_treated_mrs_dist',
'mothership_lvo_ivt_mrs_dist',
'mothership_lvo_ivt_mt_mrs_dist',
'mothership_lvo_mix_mrs_dist',
'mothership_lvo_mt_mrs_dist',
'mothership_nlvo_ivt_mrs_dist',
'mothership_weighted_mrs_dist',
'mothership_weighted_treated_mrs_dist']
Only make national statistics for areas where mothership and drip and ship are different:
mask = df_mrs['mt_transfer_required']
from statsmodels.stats.weightstats import DescrStatsW # for mRS dist stats
df_mrs_national = pd.DataFrame()
df_mrs_national_noncum = pd.DataFrame()
df_mrs_national_std = pd.DataFrame()
# Stats:
for c, col in enumerate(cols_each_scen):
cols_here = [c for c in df_mrs.columns if ((c.startswith(col)) & ('noncum' in c))]
# Split list of values into one column per mRS band
# and keep one row per LSOA.
vals = df_mrs.loc[mask, cols_here].copy()
# Create stats from these data:
weighted_stats = DescrStatsW(vals, weights=df_mrs.loc[mask, 'LSOA_predicted_admissions'], ddof=0)
# Means (one value per mRS):
means = weighted_stats.mean
# Standard deviations (one value per mRS):
stds = weighted_stats.std
# Cumulative probability from the mean bins:
cumulatives = np.cumsum(means)
# Store the data in these columns:
cols_cumulative = [f'mRS<={i}' for i in range(7)]
cols_noncum = [f'mRS={i}' for i in range(7)]
# Store in results df. Round the values to 5 decimal places.
val = col.split('_mrs_dist')[0]
df_mrs_national_noncum.loc[val, cols_noncum] = np.round(means, 5)
df_mrs_national.loc[val, cols_cumulative] = np.round(cumulatives, 5)
df_mrs_national_std.loc[val, cols_noncum] = np.round(stds, 5)
df_mrs_national
mRS<=0 | mRS<=1 | mRS<=2 | mRS<=3 | mRS<=4 | mRS<=5 | mRS<=6 | |
---|---|---|---|---|---|---|---|
drip_ship_lvo_ivt | 0.10356 | 0.19544 | 0.32788 | 0.49012 | 0.70857 | 0.82316 | 1.0 |
drip_ship_lvo_ivt_mt | 0.11472 | 0.22605 | 0.37176 | 0.54453 | 0.75047 | 0.85084 | 1.0 |
drip_ship_lvo_mix | 0.11382 | 0.22365 | 0.36835 | 0.54031 | 0.74723 | 0.84869 | 1.0 |
drip_ship_lvo_mt | 0.11449 | 0.22589 | 0.37170 | 0.54455 | 0.75052 | 0.85086 | 1.0 |
drip_ship_nlvo_ivt | 0.36134 | 0.58906 | 0.70508 | 0.82416 | 0.92123 | 0.95515 | 1.0 |
drip_ship_weighted | 0.18250 | 0.39015 | 0.51547 | 0.65399 | 0.81988 | 0.89575 | 1.0 |
drip_ship_weighted_treated | 0.23655 | 0.40482 | 0.53531 | 0.68105 | 0.83350 | 0.90148 | 1.0 |
mothership_lvo_ivt | 0.09705 | 0.18809 | 0.32101 | 0.48329 | 0.70384 | 0.81982 | 1.0 |
mothership_lvo_ivt_mt | 0.15523 | 0.27670 | 0.42080 | 0.59378 | 0.78327 | 0.87247 | 1.0 |
mothership_lvo_mix | 0.15072 | 0.26984 | 0.41306 | 0.58522 | 0.77711 | 0.86839 | 1.0 |
mothership_lvo_mt | 0.15523 | 0.27670 | 0.42080 | 0.59378 | 0.78327 | 0.87247 | 1.0 |
mothership_nlvo_ivt | 0.34442 | 0.57736 | 0.69431 | 0.81494 | 0.91617 | 0.95206 | 1.0 |
mothership_weighted | 0.18504 | 0.39450 | 0.51975 | 0.65849 | 0.82301 | 0.89784 | 1.0 |
mothership_weighted_treated | 0.24676 | 0.42231 | 0.55251 | 0.69911 | 0.84606 | 0.90988 | 1.0 |
df_mrs_national_noncum
mRS=0 | mRS=1 | mRS=2 | mRS=3 | mRS=4 | mRS=5 | mRS=6 | |
---|---|---|---|---|---|---|---|
drip_ship_lvo_ivt | 0.10356 | 0.09188 | 0.13244 | 0.16224 | 0.21845 | 0.11459 | 0.17684 |
drip_ship_lvo_ivt_mt | 0.11472 | 0.11133 | 0.14571 | 0.17277 | 0.20594 | 0.10037 | 0.14916 |
drip_ship_lvo_mix | 0.11382 | 0.10983 | 0.14470 | 0.17197 | 0.20692 | 0.10146 | 0.15131 |
drip_ship_lvo_mt | 0.11449 | 0.11139 | 0.14582 | 0.17284 | 0.20597 | 0.10034 | 0.14914 |
drip_ship_nlvo_ivt | 0.36134 | 0.22771 | 0.11603 | 0.11907 | 0.09707 | 0.03393 | 0.04485 |
drip_ship_weighted | 0.18250 | 0.20765 | 0.12532 | 0.13852 | 0.16589 | 0.07586 | 0.10425 |
drip_ship_weighted_treated | 0.23655 | 0.16828 | 0.13048 | 0.14574 | 0.15245 | 0.06798 | 0.09852 |
mothership_lvo_ivt | 0.09705 | 0.09104 | 0.13293 | 0.16228 | 0.22054 | 0.11599 | 0.18018 |
mothership_lvo_ivt_mt | 0.15523 | 0.12147 | 0.14409 | 0.17298 | 0.18949 | 0.08921 | 0.12753 |
mothership_lvo_mix | 0.15072 | 0.11911 | 0.14323 | 0.17215 | 0.19189 | 0.09128 | 0.13161 |
mothership_lvo_mt | 0.15523 | 0.12147 | 0.14409 | 0.17298 | 0.18949 | 0.08921 | 0.12753 |
mothership_nlvo_ivt | 0.34442 | 0.23294 | 0.11695 | 0.12062 | 0.10124 | 0.03589 | 0.04794 |
mothership_weighted | 0.18504 | 0.20946 | 0.12525 | 0.13873 | 0.16452 | 0.07483 | 0.10216 |
mothership_weighted_treated | 0.24676 | 0.17555 | 0.13020 | 0.14660 | 0.14695 | 0.06382 | 0.09012 |
df_mrs_national_std
mRS=0 | mRS=1 | mRS=2 | mRS=3 | mRS=4 | mRS=5 | mRS=6 | |
---|---|---|---|---|---|---|---|
drip_ship_lvo_ivt | 0.00262 | 0.00029 | 0.00022 | 0.00003 | 0.00083 | 0.00055 | 0.00129 |
drip_ship_lvo_ivt_mt | 0.00983 | 0.00399 | 0.00143 | 0.00129 | 0.00452 | 0.00355 | 0.00729 |
drip_ship_lvo_mix | 0.00924 | 0.00365 | 0.00118 | 0.00111 | 0.00422 | 0.00329 | 0.00677 |
drip_ship_lvo_mt | 0.01037 | 0.00373 | 0.00054 | 0.00080 | 0.00460 | 0.00347 | 0.00723 |
drip_ship_nlvo_ivt | 0.00667 | 0.00215 | 0.00039 | 0.00064 | 0.00160 | 0.00074 | 0.00116 |
drip_ship_weighted | 0.00180 | 0.00037 | 0.00014 | 0.00013 | 0.00067 | 0.00047 | 0.00094 |
drip_ship_weighted_treated | 0.00723 | 0.00150 | 0.00058 | 0.00052 | 0.00269 | 0.00191 | 0.00379 |
mothership_lvo_ivt | 0.00568 | 0.00090 | 0.00035 | 0.00004 | 0.00188 | 0.00128 | 0.00309 |
mothership_lvo_ivt_mt | 0.01227 | 0.00250 | 0.00093 | 0.00032 | 0.00475 | 0.00307 | 0.00577 |
mothership_lvo_mix | 0.01176 | 0.00237 | 0.00089 | 0.00030 | 0.00452 | 0.00293 | 0.00557 |
mothership_lvo_mt | 0.01227 | 0.00250 | 0.00093 | 0.00032 | 0.00475 | 0.00307 | 0.00577 |
mothership_nlvo_ivt | 0.01520 | 0.00444 | 0.00075 | 0.00131 | 0.00387 | 0.00187 | 0.00297 |
mothership_weighted | 0.00335 | 0.00026 | 0.00020 | 0.00019 | 0.00104 | 0.00060 | 0.00107 |
mothership_weighted_treated | 0.01346 | 0.00103 | 0.00082 | 0.00078 | 0.00420 | 0.00240 | 0.00428 |
Errors for weighted combinations#
Redo the standard deviations to properly propagate the errors from the separate cohorts.
LVO mix:
drip_ship_lvo_stds_before = df_mrs_national_std.loc['drip_ship_lvo_mix'].copy()
mothership_lvo_stds_before = df_mrs_national_std.loc['mothership_lvo_mix'].copy()
stds_to_combine = ['lvo_ivt', 'lvo_mt', 'lvo_ivt_mt']
for model_name in ['drip_ship', 'mothership']:
# New column names for std:
ind = f'{model_name}_lvo_mix'
# Column names of existing data:
ind_lvo_ivt = f'{model_name}_lvo_ivt'
ind_lvo_ivt_mt = f'{model_name}_lvo_ivt_mt'
ind_lvo_mt = f'{model_name}_lvo_mt'
# Weighted sum:
df_mrs_national_std.loc[ind] = np.sqrt(
(df_mrs_national_std.loc[ind_lvo_ivt].values * (proportions['lvo_ivt_only'] / prop_lvo_treated))**2.0 +
(df_mrs_national_std.loc[ind_lvo_ivt_mt].values * (proportions['lvo_ivt_mt'] / prop_lvo_treated))**2.0 +
(df_mrs_national_std.loc[ind_lvo_mt].values * (proportions['lvo_mt_only'] / prop_lvo_treated))**2.0
)
# Round to 5 decimal places:
df_mrs_national_std.loc[ind] = np.round(df_mrs_national_std.loc[ind], 5)
pd.DataFrame(
np.stack((
drip_ship_lvo_stds_before,
df_mrs_national_std.loc['drip_ship_lvo_mix'],
mothership_lvo_stds_before,
df_mrs_national_std.loc['mothership_lvo_mix']
), axis=-1),
columns=['Drip and ship before', 'Drip and ship after', 'Mothership before', 'Mothership after']
)
Drip and ship before | Drip and ship after | Mothership before | Mothership after | |
---|---|---|---|---|
0 | 0.00924 | 0.00784 | 0.01176 | 0.00978 |
1 | 0.00365 | 0.00317 | 0.00237 | 0.00199 |
2 | 0.00118 | 0.00112 | 0.00089 | 0.00074 |
3 | 0.00111 | 0.00102 | 0.00030 | 0.00025 |
4 | 0.00422 | 0.00360 | 0.00452 | 0.00378 |
5 | 0.00329 | 0.00283 | 0.00293 | 0.00245 |
6 | 0.00677 | 0.00580 | 0.00557 | 0.00460 |
Treated population mix:
drip_ship_weighted_treated_stds_before = df_mrs_national_std.loc['drip_ship_weighted_treated'].copy()
mothership_weighted_treated_stds_before = df_mrs_national_std.loc['mothership_weighted_treated'].copy()
p = prop_ischaemic_treated
for model_name in ['drip_ship', 'mothership']:
# New column names for non-cumulative and cumulative probabilities:
ind = f'{model_name}_weighted_treated'
# Column names of existing data:
ind_nlvo_ivt = f'{model_name}_nlvo_ivt'
ind_lvo_ivt = f'{model_name}_lvo_ivt'
ind_lvo_ivt_mt = f'{model_name}_lvo_ivt_mt'
ind_lvo_mt = f'{model_name}_lvo_mt'
# Weighted sum:
df_mrs_national_std.loc[ind] = np.sqrt(
(df_mrs_national_std.loc[ind_nlvo_ivt].values * (proportions['nlvo_ivt'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_ivt].values * (proportions['lvo_ivt_only'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_ivt_mt].values * (proportions['lvo_ivt_mt'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_mt].values * (proportions['lvo_mt_only'] / p))**2.0
)
# Round to 5 decimal places:
df_mrs_national_std.loc[ind] = np.round(df_mrs_national_std.loc[ind], 5)
pd.DataFrame(
np.stack((
drip_ship_weighted_treated_stds_before,
df_mrs_national_std.loc['drip_ship_weighted_treated'],
mothership_weighted_treated_stds_before,
df_mrs_national_std.loc['mothership_weighted_treated']
), axis=-1),
columns=['Drip and ship before', 'Drip and ship after', 'Mothership before', 'Mothership after']
)
Drip and ship before | Drip and ship after | Mothership before | Mothership after | |
---|---|---|---|---|
0 | 0.00723 | 0.00515 | 0.01346 | 0.00901 |
1 | 0.00150 | 0.00192 | 0.00103 | 0.00242 |
2 | 0.00058 | 0.00060 | 0.00082 | 0.00053 |
3 | 0.00052 | 0.00060 | 0.00078 | 0.00066 |
4 | 0.00269 | 0.00198 | 0.00420 | 0.00271 |
5 | 0.00191 | 0.00147 | 0.00240 | 0.00154 |
6 | 0.00379 | 0.00298 | 0.00428 | 0.00275 |
Total ischaemic population mix:
drip_ship_weighted_stds_before = df_mrs_national_std.loc['drip_ship_weighted'].copy()
mothership_weighted_stds_before = df_mrs_national_std.loc['mothership_weighted'].copy()
p = prop_ischaemic
for model_name in ['drip_ship', 'mothership']:
# New column names for non-cumulative and cumulative probabilities:
ind = f'{model_name}_weighted'
# Column names of existing data:
ind_nlvo_ivt = f'{model_name}_nlvo_ivt'
ind_lvo_ivt = f'{model_name}_lvo_ivt'
ind_lvo_ivt_mt = f'{model_name}_lvo_ivt_mt'
ind_lvo_mt = f'{model_name}_lvo_mt'
# Weighted sum:
df_mrs_national_std.loc[ind] = np.sqrt(
(df_mrs_national_std.loc[ind_nlvo_ivt].values * (proportions['nlvo_ivt'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_ivt].values * (proportions['lvo_ivt_only'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_ivt_mt].values * (proportions['lvo_ivt_mt'] / p))**2.0 +
(df_mrs_national_std.loc[ind_lvo_mt].values * (proportions['lvo_mt_only'] / p))**2.0
)
# Round to 5 decimal places:
df_mrs_national_std.loc[ind] = np.round(df_mrs_national_std.loc[ind], 5)
pd.DataFrame(
np.stack((
drip_ship_weighted_stds_before,
df_mrs_national_std.loc['drip_ship_weighted'],
mothership_weighted_stds_before,
df_mrs_national_std.loc['mothership_weighted']
), axis=-1),
columns=['Drip and ship before', 'Drip and ship after', 'Mothership before', 'Mothership after']
)
Drip and ship before | Drip and ship after | Mothership before | Mothership after | |
---|---|---|---|---|
0 | 0.00180 | 0.00128 | 0.00335 | 0.00224 |
1 | 0.00037 | 0.00048 | 0.00026 | 0.00060 |
2 | 0.00014 | 0.00015 | 0.00020 | 0.00013 |
3 | 0.00013 | 0.00015 | 0.00019 | 0.00016 |
4 | 0.00067 | 0.00049 | 0.00104 | 0.00067 |
5 | 0.00047 | 0.00037 | 0.00060 | 0.00038 |
6 | 0.00094 | 0.00074 | 0.00107 | 0.00068 |
Save results#
# Save to file:
df_mrs.to_csv(os.path.join(dir_output, 'cohort_mrs_dists_weighted.csv'))
# Save to file:
df_mrs_national.to_csv(os.path.join(dir_output, 'cohort_mrs_dists_weighted_national.csv'))
df_mrs_national_noncum.to_csv(os.path.join(dir_output, 'cohort_mrs_dists_weighted_national_noncum.csv'))
df_mrs_national_std.to_csv(os.path.join(dir_output, 'cohort_mrs_dists_weighted_national_std.csv'))
Conclusion#
We have calculated the mRS distributions for mixed cohorts of patients and for the average across England and Wales.