Drug Resistance Index (DRI)

The Drug Resistance Index or DRI measures changes through time in the proportion of disease-causing pathogens that are resistant to the antibiotics commonly used to treat them. The annual percentage change in the DRI is a measure of the rate of depletion of antibiotic effectiveness.

Since antibiotic use may change over time in response to changing levels of antibiotic resistance, we compare trends in the index with the counterfactual case, where antibiotic use remains fixed to a baseline year. A static-use DRI allows assessment of the extent to which drug use has adapted in response to resistance and the burden that this resistance would have caused if antibiotic use patterns had not changed. Changing antibiotic use patterns over time may mitigate the burden of antibiotic resistance. To incorporate changing trends in antibiotic use, we also construct an adaptive version of the DRI.

For more information see: pyamr.core.dri.DRI

 21 # Libraries
 22 import pandas as pd
 23
 24 # ----------------------------------
 25 # Create data
 26 # ----------------------------------
 27 # Define susceptibility test records
 28 susceptibility_records = [
 29     ['2021-01-01', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 30     ['2021-01-01', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 31     ['2021-01-01', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 32     ['2021-01-01', 'BLDCUL', 'ECOL', 'AAUG', 'resistant'],
 33     ['2021-01-02', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 34     ['2021-01-02', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 35     ['2021-01-02', 'BLDCUL', 'ECOL', 'AAUG', 'resistant'],
 36     ['2021-01-03', 'BLDCUL', 'ECOL', 'AAUG', 'sensitive'],
 37     ['2021-01-03', 'BLDCUL', 'ECOL', 'AAUG', 'resistant'],
 38     ['2021-01-04', 'BLDCUL', 'ECOL', 'AAUG', 'resistant'],
 39
 40     ['2021-01-01', 'BLDCUL', 'ECOL', 'ACIP', 'sensitive'],
 41     ['2021-01-01', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 42     ['2021-01-01', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 43     ['2021-01-01', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 44     ['2021-01-02', 'BLDCUL', 'ECOL', 'ACIP', 'sensitive'],
 45     ['2021-01-02', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 46     ['2021-01-02', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 47     ['2021-01-03', 'BLDCUL', 'ECOL', 'ACIP', 'sensitive'],
 48     ['2021-01-03', 'BLDCUL', 'ECOL', 'ACIP', 'resistant'],
 49     ['2021-01-04', 'BLDCUL', 'ECOL', 'ACIP', 'sensitive'],
 50
 51     ['2021-01-01', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 52     ['2021-01-01', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 53     ['2021-01-01', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 54     ['2021-01-01', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 55     ['2021-01-02', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 56     ['2021-01-02', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 57     ['2021-01-02', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 58     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 59     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 60     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 61     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 62     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 63     ['2021-01-08', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 64     ['2021-01-09', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 65     ['2021-01-09', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 66     ['2021-01-09', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 67     ['2021-01-09', 'BLDCUL', 'SAUR', 'ACIP', 'sensitive'],
 68     ['2021-01-09', 'BLDCUL', 'SAUR', 'ACIP', 'resistant'],
 69
 70     ['2021-01-12', 'URICUL', 'SAUR', 'ACIP', 'resistant'],
 71     ['2021-01-12', 'URICUL', 'SAUR', 'ACIP', 'intermediate'],
 72     ['2021-01-13', 'URICUL', 'SAUR', 'ACIP', 'resistant'],
 73     ['2021-01-13', 'URICUL', 'SAUR', 'ACIP', 'sensitive'],
 74     ['2021-01-14', 'URICUL', 'SAUR', 'ACIP', 'resistant'],
 75     ['2021-01-14', 'URICUL', 'SAUR', 'ACIP', 'resistant'],
 76     ['2021-01-15', 'URICUL', 'SAUR', 'ACIP', 'sensitive'],
 77     ['2021-01-15', 'URICUL', 'SAUR', 'ACIP', 'sensitive'],
 78     ['2021-01-16', 'URICUL', 'SAUR', 'ACIP', 'intermediate'],
 79     ['2021-01-16', 'URICUL', 'SAUR', 'ACIP', 'intermediate'],
 80 ]
 81
 82 # Define prescription test records
 83 prescription_records = [
 84     ['2021-01-01', 'PATIENT_1', 'AAUG', 150],
 85     ['2021-01-02', 'PATIENT_1', 'AAUG', 221],
 86     ['2021-01-03', 'PATIENT_1', 'AAUG', 152],
 87
 88     ['2021-01-01', 'PATIENT_2', 'AAUG', 254],
 89     ['2021-01-02', 'PATIENT_2', 'AAUG', 325],
 90     ['2021-01-03', 'PATIENT_2', 'AAUG', 356],
 91
 92     ['2021-01-01', 'PATIENT_3', 'ACIP', 457],
 93     ['2021-01-02', 'PATIENT_3', 'ACIP', 428],
 94     ['2021-01-03', 'PATIENT_3', 'ACIP', 459],
 95
 96     ['2021-01-01', 'PATIENT_4', 'ACIP', 50],
 97     ['2021-01-02', 'PATIENT_4', 'ACIP', 50],
 98     ['2021-01-03', 'PATIENT_4', 'ACIP', 50],
 99
100 ]
101
102 # Create DataFrames
103 susceptibility = pd.DataFrame(susceptibility_records,
104                               columns=['DATE',
105                                        'SPECIMEN',
106                                        'MICROORGANISM',
107                                        'ANTIMICROBIAL',
108                                        'SENSITIVITY'])
109
110 prescriptions = pd.DataFrame(prescription_records,
111                              columns=['DATE',
112                                       'PATIENT',
113                                       'DRUG',
114                                       'DOSE'])
115
116 # Format dates
117 susceptibility.DATE = pd.to_datetime(susceptibility.DATE)
118 prescriptions.DATE = pd.to_datetime(prescriptions.DATE)

Lets see the susceptibility test records

122 susceptibility.head(5)
DATE SPECIMEN MICROORGANISM ANTIMICROBIAL SENSITIVITY
0 2021-01-01 BLDCUL ECOL AAUG sensitive
1 2021-01-01 BLDCUL ECOL AAUG sensitive
2 2021-01-01 BLDCUL ECOL AAUG sensitive
3 2021-01-01 BLDCUL ECOL AAUG resistant
4 2021-01-02 BLDCUL ECOL AAUG sensitive


Lets see the prescription records

126 prescriptions.head(5)
DATE PATIENT DRUG DOSE
0 2021-01-01 PATIENT_1 AAUG 150
1 2021-01-02 PATIENT_1 AAUG 221
2 2021-01-03 PATIENT_1 AAUG 152
3 2021-01-01 PATIENT_2 AAUG 254
4 2021-01-02 PATIENT_2 AAUG 325


Lets create the summary table and compute the DRI

132 # ------------------------
133 # Compute summary table
134 # ------------------------
135 # Libraries
136 from pyamr.core.sari import SARI
137
138 # Create sari instance
139 sari = SARI(groupby=['DATE',
140                      'SPECIMEN',
141                      'MICROORGANISM',
142                      'ANTIMICROBIAL',
143                      'SENSITIVITY'])
144
145 # Compute susceptibility summary table
146 smmry1 = sari.compute(susceptibility,
147                       return_frequencies=False)
148
149 # Compute prescriptions summary table.
150 smmry2 = prescriptions \
151     .groupby(by=['DATE', 'DRUG']) \
152     .DOSE.sum().rename('use')
153
154 # Combine both summary tables
155 smmry = smmry1.reset_index().merge(
156     smmry2.reset_index(), how='inner',
157     left_on=['DATE', 'ANTIMICROBIAL'],
158     right_on=['DATE', 'DRUG']
159 )
160
161 # -------------------------
162 # Compute DRI
163 # -------------------------
164 # Librarie
165 from pyamr.core.dri import DRI
166
167 # Instance
168 obj = DRI(
169     column_resistance='sari',
170     column_usage='use'
171 )
172
173 # Compute DRI overall
174 dri1 = obj.compute(smmry)
175
176 # Compute DRI
177 dri2 = obj.compute(smmry,
178     groupby=['SPECIMEN'])
179
180 # Compute DRI
181 dri3 = obj.compute(smmry,
182     groupby=['MICROORGANISM'])
183
184 # Compute DRI
185 dri4 = obj.compute(smmry,
186     groupby=['MICROORGANISM', 'ANTIMICROBIAL'])
187
188 # Compute DRI
189 dri5 = obj.compute(smmry,
190     groupby=['DATE'],
191     return_usage=True)
192
193 # Compute DRI
194 dri6 = obj.compute(smmry,
195     groupby=['DATE', 'MICROORGANISM'],
196     return_usage=True)
197
198 # Compute DRI
199 dri7 = obj.compute(smmry,
200     groupby=['DATE', 'MICROORGANISM', 'ANTIMICROBIAL'],
201     return_usage=True,
202     return_complete=True)
203
204 # Compute DRI (return all elements of summary table).
205 dri8 = obj.compute(smmry,
206     groupby=['MICROORGANISM'],
207     return_complete=True)
208
209 # Show
210 print("\nDRI (1):")
211 print(dri1)
212 print("\nDRI (2):")
213 print(dri2)
214 print("\nDRI (3):")
215 print(dri3)
216 print("\nDRI (4):")
217 print(dri4)
218 print("\nDRI (5):")
219 print(dri5)
220 print("\nDRI (6):")
221 print(dri6)
222 print("\nDRI (7):")
223 print(dri7)
224 print("\nDRI (8):")
225 print(dri8)
DRI (1):
0.5478155956311913

DRI (2):
SPECIMEN
BLDCUL    0.5478
Name: dri, dtype: float64

DRI (3):
MICROORGANISM
ECOL    0.5049
SAUR    0.6765
Name: dri, dtype: float64

DRI (4):
MICROORGANISM  ANTIMICROBIAL
ECOL           AAUG             0.3683
               ACIP             0.6382
SAUR           ACIP             0.6765
Name: dri, dtype: float64

DRI (5):
            use_period     dri
DATE
2021-01-01      1418.0  0.6969
2021-01-02      1502.0  0.4394
2021-01-03      1017.0  0.5000

DRI (6):
                          use_period     dri
DATE       MICROORGANISM
2021-01-01 ECOL                911.0  0.5283
           SAUR                507.0  1.0000
2021-01-02 ECOL               1024.0  0.4889
           SAUR                478.0  0.3333
2021-01-03 ECOL               1017.0  0.5000

DRI (7):
                                               DATE SPECIMEN MICROORGANISM ANTIMICROBIAL  RESISTANCE  DRUG  USE  use_period  u_weight  w_rate     dri
DATE       MICROORGANISM ANTIMICROBIAL
2021-01-01 ECOL          AAUG          0 2021-01-01   BLDCUL          ECOL          AAUG      0.2500  AAUG  404         404       1.0  0.2500  0.2500
                         ACIP          1 2021-01-01   BLDCUL          ECOL          ACIP      0.7500  ACIP  507         507       1.0  0.7500  0.7500
           SAUR          ACIP          2 2021-01-01   BLDCUL          SAUR          ACIP      1.0000  ACIP  507         507       1.0  1.0000  1.0000
2021-01-02 ECOL          AAUG          3 2021-01-02   BLDCUL          ECOL          AAUG      0.3333  AAUG  546         546       1.0  0.3333  0.3333
                         ACIP          4 2021-01-02   BLDCUL          ECOL          ACIP      0.6667  ACIP  478         478       1.0  0.6667  0.6667
           SAUR          ACIP          5 2021-01-02   BLDCUL          SAUR          ACIP      0.3333  ACIP  478         478       1.0  0.3333  0.3333
2021-01-03 ECOL          AAUG          6 2021-01-03   BLDCUL          ECOL          AAUG      0.5000  AAUG  508         508       1.0  0.5000  0.5000
                         ACIP          7 2021-01-03   BLDCUL          ECOL          ACIP      0.5000  ACIP  509         509       1.0  0.5000  0.5000

DRI (8):
                      DATE SPECIMEN MICROORGANISM ANTIMICROBIAL  RESISTANCE  DRUG  USE  use_period  u_weight  w_rate     dri
MICROORGANISM
ECOL          0 2021-01-01   BLDCUL          ECOL          AAUG      0.2500  AAUG  404        2952    0.1369  0.0342  0.5049
              1 2021-01-01   BLDCUL          ECOL          ACIP      0.7500  ACIP  507        2952    0.1717  0.1288  0.5049
              3 2021-01-02   BLDCUL          ECOL          AAUG      0.3333  AAUG  546        2952    0.1850  0.0617  0.5049
              4 2021-01-02   BLDCUL          ECOL          ACIP      0.6667  ACIP  478        2952    0.1619  0.1079  0.5049
              6 2021-01-03   BLDCUL          ECOL          AAUG      0.5000  AAUG  508        2952    0.1721  0.0860  0.5049
              7 2021-01-03   BLDCUL          ECOL          ACIP      0.5000  ACIP  509        2952    0.1724  0.0862  0.5049
SAUR          2 2021-01-01   BLDCUL          SAUR          ACIP      1.0000  ACIP  507         985    0.5147  0.5147  0.6765
              5 2021-01-02   BLDCUL          SAUR          ACIP      0.3333  ACIP  478         985    0.4853  0.1618  0.6765

Lets see the summary table

229 smmry
DATE SPECIMEN MICROORGANISM ANTIMICROBIAL sari DRUG use
0 2021-01-01 BLDCUL ECOL AAUG 0.2500 AAUG 404
1 2021-01-01 BLDCUL ECOL ACIP 0.7500 ACIP 507
2 2021-01-01 BLDCUL SAUR ACIP 1.0000 ACIP 507
3 2021-01-02 BLDCUL ECOL AAUG 0.3333 AAUG 546
4 2021-01-02 BLDCUL ECOL ACIP 0.6667 ACIP 478
5 2021-01-02 BLDCUL SAUR ACIP 0.3333 ACIP 478
6 2021-01-03 BLDCUL ECOL AAUG 0.5000 AAUG 508
7 2021-01-03 BLDCUL ECOL ACIP 0.5000 ACIP 509


Lets see the sample 4.

233 dri4.to_frame().round(decimals=3)
dri
MICROORGANISM ANTIMICROBIAL
ECOL AAUG 0.368
ACIP 0.638
SAUR ACIP 0.676


Lets see the sample 7 with return_components=True.

237 dri7.rename(columns={
238     'MICROORGANISM': 'ORG',
239     'ANTIMICROBIAL': 'ABX'
240 }).round(decimals=3)
DATE SPECIMEN ORG ABX RESISTANCE DRUG USE use_period u_weight w_rate dri
DATE MICROORGANISM ANTIMICROBIAL
2021-01-01 ECOL AAUG 0 2021-01-01 BLDCUL ECOL AAUG 0.250 AAUG 404 404 1.0 0.250 0.250
ACIP 1 2021-01-01 BLDCUL ECOL ACIP 0.750 ACIP 507 507 1.0 0.750 0.750
SAUR ACIP 2 2021-01-01 BLDCUL SAUR ACIP 1.000 ACIP 507 507 1.0 1.000 1.000
2021-01-02 ECOL AAUG 3 2021-01-02 BLDCUL ECOL AAUG 0.333 AAUG 546 546 1.0 0.333 0.333
ACIP 4 2021-01-02 BLDCUL ECOL ACIP 0.667 ACIP 478 478 1.0 0.667 0.667
SAUR ACIP 5 2021-01-02 BLDCUL SAUR ACIP 0.333 ACIP 478 478 1.0 0.333 0.333
2021-01-03 ECOL AAUG 6 2021-01-03 BLDCUL ECOL AAUG 0.500 AAUG 508 508 1.0 0.500 0.500
ACIP 7 2021-01-03 BLDCUL ECOL ACIP 0.500 ACIP 509 509 1.0 0.500 0.500


Lets see the sample 8 with return_complete=True.

244 dri8.rename(columns={
245     'MICROORGANISM': 'ORG',
246     'ANTIMICROBIAL': 'ABX'
247 }).round(decimals=3)
DATE SPECIMEN ORG ABX RESISTANCE DRUG USE use_period u_weight w_rate dri
MICROORGANISM
ECOL 0 2021-01-01 BLDCUL ECOL AAUG 0.250 AAUG 404 2952 0.137 0.034 0.505
1 2021-01-01 BLDCUL ECOL ACIP 0.750 ACIP 507 2952 0.172 0.129 0.505
3 2021-01-02 BLDCUL ECOL AAUG 0.333 AAUG 546 2952 0.185 0.062 0.505
4 2021-01-02 BLDCUL ECOL ACIP 0.667 ACIP 478 2952 0.162 0.108 0.505
6 2021-01-03 BLDCUL ECOL AAUG 0.500 AAUG 508 2952 0.172 0.086 0.505
7 2021-01-03 BLDCUL ECOL ACIP 0.500 ACIP 509 2952 0.172 0.086 0.505
SAUR 2 2021-01-01 BLDCUL SAUR ACIP 1.000 ACIP 507 985 0.515 0.515 0.676
5 2021-01-02 BLDCUL SAUR ACIP 0.333 ACIP 478 985 0.485 0.162 0.676


Lets compute the fixed index for comparison

252 # --------------------------------------------
253 # Compute DRI fixed
254 # --------------------------------------------
255 # Compute prescriptions on t0.
256 use_t0 = prescriptions \
257     .groupby(by=['DATE', 'DRUG']) \
258     .DOSE.sum().rename('use') \
259     .to_frame().reset_index() \
260     .groupby('DRUG').use.first()
261
262 # Add to summary table
263 smmry = smmry.assign(use_t0=smmry.DRUG.map(use_t0))
264
265 # Define groupby
266 groupby = [
267     'DATE',
268     'MICROORGANISM'
269 ]
270
271 # Compute DRI
272 dri9a = obj.compute(smmry,
273                     groupby=groupby,
274                     return_usage=True)
275
276 # Compute DRI using new USE
277 dri9b = obj.compute(smmry,
278                     groupby=groupby,
279                     return_usage=True,
280                     column_usage='use_t0')
281
282 # aux = pd.concat([dri9a, dri9b], axis=1)
283 aux = dri9a.merge(dri9b,
284                   left_index=True, right_index=True,
285                   suffixes=['', '_fixed'])
286
287 # Concatenate (series)
288 # aux = pd.concat([
289 #    dri9a.rename('dri'),
290 #    dri9b.rename('dri_fixed')], axis=1)
291
292 # Show
293 print("\n\n")
294 print("\nSummary (variable):")
295 print(smmry)
296 print("\nDRI (9):")
297 print(aux)
Summary (variable):
        DATE SPECIMEN MICROORGANISM ANTIMICROBIAL    sari  DRUG  use  use_t0
0 2021-01-01   BLDCUL          ECOL          AAUG  0.2500  AAUG  404     404
1 2021-01-01   BLDCUL          ECOL          ACIP  0.7500  ACIP  507     507
2 2021-01-01   BLDCUL          SAUR          ACIP  1.0000  ACIP  507     507
3 2021-01-02   BLDCUL          ECOL          AAUG  0.3333  AAUG  546     404
4 2021-01-02   BLDCUL          ECOL          ACIP  0.6667  ACIP  478     507
5 2021-01-02   BLDCUL          SAUR          ACIP  0.3333  ACIP  478     507
6 2021-01-03   BLDCUL          ECOL          AAUG  0.5000  AAUG  508     404
7 2021-01-03   BLDCUL          ECOL          ACIP  0.5000  ACIP  509     507

DRI (9):
                          use_period     dri  use_period_fixed  dri_fixed
DATE       MICROORGANISM
2021-01-01 ECOL                911.0  0.5283             911.0     0.5283
           SAUR                507.0  1.0000             507.0     1.0000
2021-01-02 ECOL               1024.0  0.4889             911.0     0.5188
           SAUR                478.0  0.3333             507.0     0.3333
2021-01-03 ECOL               1017.0  0.5000             911.0     0.5000

Lets see the new summary (added old use column <old> for comparison)

302 smmry
DATE SPECIMEN MICROORGANISM ANTIMICROBIAL sari DRUG use use_t0
0 2021-01-01 BLDCUL ECOL AAUG 0.2500 AAUG 404 404
1 2021-01-01 BLDCUL ECOL ACIP 0.7500 ACIP 507 507
2 2021-01-01 BLDCUL SAUR ACIP 1.0000 ACIP 507 507
3 2021-01-02 BLDCUL ECOL AAUG 0.3333 AAUG 546 404
4 2021-01-02 BLDCUL ECOL ACIP 0.6667 ACIP 478 507
5 2021-01-02 BLDCUL SAUR ACIP 0.3333 ACIP 478 507
6 2021-01-03 BLDCUL ECOL AAUG 0.5000 AAUG 508 404
7 2021-01-03 BLDCUL ECOL ACIP 0.5000 ACIP 509 507


Lets see the results for both fixed and dynamic.

306 aux
use_period dri use_period_fixed dri_fixed
DATE MICROORGANISM
2021-01-01 ECOL 911.0 0.5283 911.0 0.5283
SAUR 507.0 1.0000 507.0 1.0000
2021-01-02 ECOL 1024.0 0.4889 911.0 0.5188
SAUR 478.0 0.3333 507.0 0.3333
2021-01-03 ECOL 1017.0 0.5000 911.0 0.5000


Lets visualise it

311 # --------------------------
312 # Plot
313 # --------------------------
314 # Libraries
315 import matplotlib.pyplot as plt
316 import seaborn as sns
317
318 # Filter
319 stacked = aux[['dri', 'dri_fixed']].stack().reset_index()
320
321 # Display using relplot
322 sns.relplot(data=stacked,
323     x='DATE', y=0, row='MICROORGANISM', hue='level_2',
324     # hue='event', style='event', col='region', palette='palette',
325     #height=4, aspect=2.0,
326     kind='line', linewidth=1.00, markersize=6, marker='o'
327 )
328
329 # Show
330 plt.show()
MICROORGANISM = ECOL, MICROORGANISM = SAUR

Note

The summary table for the prescriptions data computed above aggregated the values in the column dose which indicates the specific dose delivered to the patient. In many scenarios, this information might not be available or dosage units might vary (e.g. mg or ml). A possible workaround is to count the number of entries in the prescriptions data by using DOSE.count() but this workaround should be use with caution.

Total running time of the script: ( 0 minutes 0.649 seconds)

Gallery generated by Sphinx-Gallery