Note
Go to the end to download the full example code
Step 01 - Compute AMR metrics
Loading susceptibility test data
A Susceptibility test record (see figure 4.1) is composed by laboratory
identification number (LID), patient identification number (PID), date, sample
type, specimen or culture (e.g. blood or urine), pathogen, antimicrobial, reported
status and outcome (resistant, sensitive or intermediate). In this research,
the susceptibility test data were grouped firstly by specimen type. Moreover,
for each sample type, the data were grouped by pairs (pathogen, antimicrobial)
since it is widely accepted by clinicians as detailed in the UK five year
strategy in AMR.
A small dataset will be used for this example.
28 # Libraries
29 import numpy as np
30 import pandas as pd
31 import seaborn as sns
32 import matplotlib as mpl
33 import matplotlib.pyplot as plt
34
35 # Import from pyAMR
36 from pyamr.datasets.load import make_susceptibility
37
38 try:
39     __file__
40     TERMINAL = True
41 except:
42     TERMINAL = False
43
44 # -------------------------------------------
45 # Load data
46 # -------------------------------------------
47 # Load data
48 data = make_susceptibility()
49 data = data.drop_duplicates()
50
51 # Show
52 print("\nData:")
53 print(data)
54 print("\nColumns:")
55 print(data.dtypes)
56 print("\nUnique:")
57 print(data[[
58     'microorganism_code',
59     'antimicrobial_code',
60     'specimen_code',
61     'laboratory_number',
62     'patient_id']].nunique())
Data:
       date_received  date_outcome  patient_id laboratory_number specimen_code  specimen_name specimen_description  ... microorganism_name antimicrobial_code antimicrobial_name sensitivity_method  sensitivity mic  reported
0         2009-01-03           NaN       20091           X428501        BLDCUL            NaN                blood  ...         klebsiella               AAMI           amikacin                NaN    sensitive NaN       NaN
1         2009-01-03           NaN       20091           X428501        BLDCUL            NaN                blood  ...         klebsiella               AAMO        amoxycillin                NaN    resistant NaN       NaN
2         2009-01-03           NaN       20091           X428501        BLDCUL            NaN                blood  ...         klebsiella               AAUG          augmentin                NaN    sensitive NaN       NaN
3         2009-01-03           NaN       20091           X428501        BLDCUL            NaN                blood  ...         klebsiella               AAZT          aztreonam                NaN    sensitive NaN       NaN
4         2009-01-03           NaN       20091           X428501        BLDCUL            NaN                blood  ...         klebsiella               ACAZ        ceftazidime                NaN    sensitive NaN       NaN
...              ...           ...         ...               ...           ...            ...                  ...  ...                ...                ...                ...                ...          ...  ..       ...
319117    2009-12-31           NaN       24645          H2012337        BLDCUL            NaN                blood  ...       enterococcus               AAMO        amoxycillin                NaN    sensitive NaN       NaN
319118    2009-12-31           NaN       24645          H2012337        BLDCUL            NaN                blood  ...       enterococcus               ALIN          linezolid                NaN    sensitive NaN       NaN
319119    2009-12-31           NaN       24645          H2012337        BLDCUL            NaN                blood  ...       enterococcus               ASYN           synercid                NaN    resistant NaN       NaN
319120    2009-12-31           NaN       24645          H2012337        BLDCUL            NaN                blood  ...       enterococcus               ATEI        teicoplanin                NaN    sensitive NaN       NaN
319121    2009-12-31           NaN       24645          H2012337        BLDCUL            NaN                blood  ...       enterococcus               AVAN         vancomycin                NaN    sensitive NaN       NaN
[319122 rows x 15 columns]
Columns:
date_received            object
date_outcome            float64
patient_id                int64
laboratory_number        object
specimen_code            object
specimen_name           float64
specimen_description     object
microorganism_code       object
microorganism_name       object
antimicrobial_code       object
antimicrobial_name       object
sensitivity_method      float64
sensitivity              object
mic                     float64
reported                float64
dtype: object
Unique:
microorganism_code       67
antimicrobial_code       58
specimen_code            22
laboratory_number     34816
patient_id            24646
dtype: int64
Computing SARI
The Single Antimicrobial Resistance Index or SARI describes the proportion
of resistant isolates for a given set of susceptibility tests. It provides a
value within the range [0, 1] where values close to one indicate high resistance.
It is agnostic to pathogen, antibiotic and/or time. The variables R, I and
S represent the number of susceptibility tests with Resistant, Intermediate and
Susceptible outcomes respectively. The definition might vary slightly since the
intermediate category is not always considered.
For more information see: pyamr.core.sari.SARI
For more examples see:
 87 # -------------------------------------------
 88 # Compute SARI
 89 # -------------------------------------------
 90 # Libraries
 91 from pyamr.core.sari import SARI
 92
 93 # Create sari instance
 94 sari = SARI(groupby=['specimen_code',
 95                      'microorganism_name',
 96                      'antimicrobial_name',
 97                      'sensitivity'])
 98
 99 # Compute SARI overall
100 sari_overall = sari.compute(data,
101     return_frequencies=True)
102
103 # Show
104 print("SARI (overall):")
105 print(sari_overall)
106
107 # ------------
108 # Plot Heatmap
109 # ------------
110 # Filter
111 matrix = sari_overall.copy(deep=True)
112 matrix = matrix.reset_index()
113 matrix = matrix[matrix.freq > 100]
114 matrix = matrix[matrix.specimen_code.isin(['BLDCUL'])]
115
116 # Pivot table
117 matrix = pd.pivot_table(matrix,
118     index='microorganism_name',
119     columns='antimicrobial_name',
120     values='sari')
121
122 # Create figure
123 f, ax = plt.subplots(1, 1, figsize=(10, 4))
124
125 # Create colormap
126 cmap = sns.color_palette("Reds", desat=0.5, n_colors=10)
127
128 # Plot
129 ax = sns.heatmap(data=matrix*100, annot=True, fmt=".0f",
130     annot_kws={'fontsize': 'small'}, cmap=cmap,
131     linewidth=0.5, vmin=0, vmax=100, ax=ax,
132     xticklabels=1, yticklabels=1)
133
134 # Add title
135 plt.suptitle("Antibiogram", fontsize='xx-large')
136
137 # Tight layout
138 plt.tight_layout()
139 plt.subplots_adjust(right=1.05)

SARI (overall):
                                                                        intermediate  resistant  sensitive  freq      sari
specimen_code microorganism_name                    antimicrobial_name
BFLCUL        anaerobes                             metronidazole                0.0        0.0        1.0   1.0  0.000000
              bacillus                              ciprofloxacin                0.0        0.0        1.0   1.0  0.000000
                                                    clindamycin                  0.0        3.0        1.0   4.0  0.750000
                                                    erythromycin                 0.0        1.0        3.0   4.0  0.250000
                                                    fusidic acid                 0.0        3.0        1.0   4.0  0.750000
...                                                                              ...        ...        ...   ...       ...
XINCUL        streptococcus beta-haemolytic group b cephalexin                   0.0        1.0        0.0   1.0  1.000000
                                                    clindamycin                  0.0        1.0        8.0   9.0  0.111111
                                                    erythromycin                 0.0        1.0        8.0   9.0  0.111111
                                                    penicillin                   0.0        0.0        9.0   9.0  0.000000
                                                    tetracycline                 0.0        8.0        1.0   9.0  0.888889
[4491 rows x 5 columns]
Computing MARI
Warning
Pending… similar to SARI.
Computing ASAI
The antimicrobial spectrum of activity refers to the range of microbe species that are susceptible to these agents and therefore can be treated. In general, antimicrobial agents are classified into broad, intermediate or narrow spectrum. Broad spectrum antimicrobials are active against both Gram-positive and Gram-negative bacteria. In contrast, narrow spectrum antimicrobials have limited activity and are effective only against particular species of bacteria. While these profiles appeared in the mid-1950s, little effort has been made to define them. Furthermore, such ambiguous labels are overused for different and even contradictory purposes.
In order to compute the antimicrobial spectrum of activity index or ASAI, it
is necessary to previously obtain the overall resistance (SARI) for all the
microbe-antimicrobial pairs. Furthermore, by following the criteria used in the
narrow-broad approach, these pairs were grouped into Gram-positive and Gram-negative.
Briefly, the weighted proportion of species to which the antimicrobial
is effective is computed for each genus. These are later added up and normalized by
the number of genera tested. An antimicrobial is considered effective to treat a
particular species when the corresponding resistance index (SARI) is lower than
a given threshold.
For more information see: pyamr.core.asai.ASAI
For more examples see:
In order to compute ASAI, we need to have the following columns present
in our dataset: antimicrobial, microorganism_genus, microorganism_species
and resistance.  Moreover, in this example we will compute the ASAI for each
gram_stain category independently so we will need the microorganism gram stain
information too. This information is available in the registries:
pyamr.datasets.registries
Lets include all this information using the MicroorganismRegistry.
191 # ------------------------------
192 # Include gram stain
193 # ------------------------------
194 # Libraries
195 from pyamr.datasets.registries import MicroorganismRegistry
196
197 # Load registry
198 mreg = MicroorganismRegistry()
199
200 # Format sari dataframe
201 dataframe = sari_overall.copy(deep=True)
202 dataframe = dataframe.reset_index()
203
204 # Create genus and species
205 dataframe[['genus', 'species']] = \
206     dataframe.microorganism_name \
207         .str.capitalize() \
208         .str.split(expand=True, n=1)
209
210 # Combine with registry information
211 dataframe = mreg.combine(dataframe, on='microorganism_name')
212
213 # Fill missing gram stain
214 dataframe.gram_stain = dataframe.gram_stain.fillna('u')
Now that we have the genus, species and gram_stain information,
lets compute ASAI.
222 # -------------------------------------------
223 # Compute ASAI
224 # -------------------------------------------
225 # Import specific libraries
226 from pyamr.core.asai import ASAI
227
228 # Create asai instance
229 asai = ASAI(column_genus='genus',
230             column_specie='species',
231             column_resistance='sari',
232             column_frequency='freq')
233
234 # Compute
235 scores = asai.compute(dataframe,
236     groupby=['specimen_code',
237              'antimicrobial_name',
238              'gram_stain'],
239     weights='uniform',
240     threshold=0.5,
241     min_freq=0)
242
243 # Stack
244 scores = scores.unstack()
245
246 # Filter and drop index.
247 scores = scores.filter(like='URICUL', axis=0)
248 scores.index = scores.index.droplevel()
249
250 # Show
251 print("\nASAI (overall):")
252 print(scores)
c:\users\kelda\desktop\repositories\github\pyamr\main\pyamr\core\asai.py:572: UserWarning:
                 Extreme resistances [0, 1] were found in the DataFrame. These
                 rows should be reviewed since these resistances might correspond
                 to pairs with low number of records.
c:\users\kelda\desktop\repositories\github\pyamr\main\pyamr\core\asai.py:583: UserWarning:
                 There are NULL values in columns that are required. These
                 rows will be ignored to safely compute ASAI. Please review
                 the DataFrame and address this inconsistencies. See below
                 for more information:
                        specimen_code            0
                        antimicrobial_name       0
                        gram_stain               0
                        GENUS                    0
                        SPECIE                2414
                        RESISTANCE               0
ASAI (overall):
                   N_GENUS          N_SPECIE          ASAI_SCORE
gram_stain               n    p   u        n    p   u          n         p   u
antimicrobial_name
amikacin               5.0  NaN NaN      5.0  NaN NaN   0.800000       NaN NaN
amoxycillin            2.0  2.0 NaN      2.0  7.0 NaN   0.500000  0.833333 NaN
amp c markers          4.0  NaN NaN      4.0  NaN NaN   0.250000       NaN NaN
augmentin              5.0  2.0 NaN      5.0  7.0 NaN   0.200000  1.000000 NaN
aztreonam              3.0  NaN NaN      3.0  NaN NaN   0.666667       NaN NaN
cefotaxime             5.0  NaN NaN      5.0  NaN NaN   0.200000       NaN NaN
cefoxitin              5.0  NaN NaN      5.0  NaN NaN   0.400000       NaN NaN
cefpodoxime            5.0  2.0 NaN      5.0  5.0 NaN   0.400000  0.833333 NaN
ceftazidime            5.0  NaN NaN      5.0  NaN NaN   0.600000       NaN NaN
cefuroxime             5.0  NaN NaN      5.0  NaN NaN   0.000000       NaN NaN
cephalexin             5.0  2.0 NaN      5.0  7.0 NaN   0.200000  0.875000 NaN
ciprofloxacin          6.0  2.0 NaN      6.0  7.0 NaN   0.333333  0.875000 NaN
clindamycin            NaN  2.0 NaN      NaN  4.0 NaN        NaN  1.000000 NaN
colistin sulphate      5.0  NaN NaN      5.0  NaN NaN   0.800000       NaN NaN
cotrimoxazole          3.0  NaN NaN      3.0  NaN NaN   0.333333       NaN NaN
ertapenem              3.0  NaN NaN      3.0  NaN NaN   0.666667       NaN NaN
erythromycin           NaN  2.0 NaN      NaN  6.0 NaN        NaN  0.833333 NaN
esbl markers           5.0  NaN NaN      5.0  NaN NaN   0.200000       NaN NaN
flucloxacillin         1.0  1.0 NaN      1.0  3.0 NaN   0.000000  1.000000 NaN
fusidic acid           NaN  1.0 NaN      NaN  3.0 NaN        NaN  0.666667 NaN
gentamicin             5.0  1.0 NaN      5.0  3.0 NaN   0.800000  1.000000 NaN
imipenem               5.0  NaN NaN      5.0  NaN NaN   0.600000       NaN NaN
linezolid              NaN  1.0 NaN      NaN  3.0 NaN        NaN  1.000000 NaN
mecillinam             5.0  NaN NaN      5.0  NaN NaN   0.400000       NaN NaN
meropenem              5.0  NaN NaN      5.0  NaN NaN   0.600000       NaN NaN
mls markers            NaN  1.0 NaN      NaN  3.0 NaN        NaN  0.333333 NaN
mupirocin              NaN  1.0 NaN      NaN  2.0 NaN        NaN  1.000000 NaN
naladixic acid         1.0  NaN NaN      1.0  NaN NaN   1.000000       NaN NaN
nitrofurantoin         5.0  2.0 NaN      5.0  7.0 NaN   0.200000  1.000000 NaN
novobiocin             1.0  1.0 NaN      1.0  3.0 NaN   0.000000  0.666667 NaN
penicillin             1.0  2.0 NaN      1.0  6.0 NaN   0.000000  0.500000 NaN
rifampicin             NaN  1.0 NaN      NaN  3.0 NaN        NaN  1.000000 NaN
sulphamethoxazole      2.0  NaN NaN      2.0  NaN NaN   0.500000       NaN NaN
tazocin                5.0  NaN NaN      5.0  NaN NaN   0.800000       NaN NaN
teicoplanin            NaN  2.0 NaN      NaN  7.0 NaN        NaN  1.000000 NaN
temocillin             3.0  NaN NaN      3.0  NaN NaN   0.666667       NaN NaN
tetracycline           1.0  2.0 NaN      1.0  6.0 NaN   1.000000  0.833333 NaN
timentin               4.0  NaN NaN      4.0  NaN NaN   0.750000       NaN NaN
tobramycin             5.0  NaN NaN      5.0  NaN NaN   0.600000       NaN NaN
trimethoprim           5.0  2.0 NaN      5.0  7.0 NaN   0.200000  1.000000 NaN
vancomycin             NaN  2.0 NaN      NaN  7.0 NaN        NaN  1.000000 NaN
This is the information obtained where the columns n, p, and u stand for gram-positive, gram-negative and unknown respectively. Similarly, N_GENUS and N_SPECIE indicates the number of genus and species for the specific antimicrobial.
259 scores.head(10)
Lets plot it now!
265 # ---------------------------------------------------------------
266 # Plot
267 # ---------------------------------------------------------------
268 # .. note: In order to sort the scores we need to compute metrics
269 #          that combine the different subcategories (e.g. gram-negative
270 #          and gram-positive). Two possible options are: (i) use the
271 #          gmean or (ii) the width.
272
273 # Libraries
274 from pyamr.utils.plot import scalar_colormap
275
276 # Measures
277 scores['width'] = np.abs(scores['ASAI_SCORE'].sum(axis=1))
278
279 # Variables to plot.
280 x = scores.index.values
281 y_n = scores['ASAI_SCORE']['n'].values
282 y_p = scores['ASAI_SCORE']['p'].values
283 y_u = scores['ASAI_SCORE']['u'].values
284
285 # Constants
286 colormap_p = scalar_colormap(y_p, cmap='Blues', vmin=-0.1, vmax=1.1)
287 colormap_n = scalar_colormap(y_n, cmap='Reds', vmin=-0.1, vmax=1.1)
288 colormap_u = scalar_colormap(y_u, cmap='Greens', vmin=-0.1, vmax=1.1)
289
290 # ----------
291 # Example
292 # ----------
293 # This example shows an stacked figure using more than two categories.
294 # For instance, it uses gram-positive, gram-negative and gram-unknown.
295 # All the indexes go within the range [0,1].
296 # Create the figure
297 f, axes = plt.subplots(1, 3, figsize=(7, 9))
298
299 # Plot each category
300 sns.barplot(x=y_p, y=x, palette=colormap_p, ax=axes[0], orient='h',
301             saturation=0.5, label='Gram-positive')
302 sns.barplot(x=y_n, y=x, palette=colormap_n, ax=axes[1], orient='h',
303             saturation=0.5, label='Gram-negative')
304 sns.barplot(x=y_u, y=x, palette=colormap_u, ax=axes[2], orient='h',
305             saturation=0.5, label='Gram-unknown')
306
307 # Configure
308 sns.despine(bottom=True)
309
310 # Format figure
311 plt.subplots_adjust(wspace=0.0, hspace=0.0)
312
313 # Remove yticks
314 axes[1].set_yticks([])
315 axes[2].set_yticks([])
316
317 # Set title
318 axes[0].set_title('Gram-positive')
319 axes[1].set_title('Gram-negative')
320 axes[2].set_title('Gram-unknown')
321
322 # Set x-axis
323 axes[0].set_xlim([0, 1.1])
324 axes[1].set_xlim([0, 1.1])
325 axes[2].set_xlim([0, 1.1])
326
327 # Adjust
328 plt.tight_layout()

Computing SART
The single antimicrobial resistance trend or SART measures the ratio
of change per time unit (e.g. monthly or yearly). To compute this metric,
it is necessary to generate a resistance time series from the susceptibility
test data. This is often achieved by computing the SARI on consecutive or
overlapping partitions of the data. Then, the trend can be extracted using
for example a linear model where the slope, which is represented by a value
within the range [-1, 1], indicates the ratio of change.
For more information see: pyamr.core.sart.SART
For more examples see:
Note
Be cautious when computing the SART index using a small dataset
(e.g. a low number of susceptibility tests records) since it is very
likely that the statistics produced (e.g. kurtosis or skewness) will
be ill defined. Also remember to check stationarity if using ARIMA.
Since it is necessary to have a decent amount of records to be able to compute the trends accurately, lets see which tuples have more number of samples.
361 # -------------------------------------------
362 # Show top combinations
363 # -------------------------------------------
364 from pyamr.core.sari import SARI
365
366 # Create SARI instance
367 sar = SARI(groupby=['specimen_code',
368                     'microorganism_code',
369                     'antimicrobial_code',
370                     'sensitivity'])
371
372 # Compute SARI overall
373 sari_overall = sar.compute(data,
374      return_frequencies=True)
375
376 # Compute top tuples
377 top = sari_overall \
378     .sort_values(by='freq', ascending=False) \
379     .head(10)
380
381 # Show
382 print("\nTop by Frequency:")
383 print(top)
Top by Frequency:
                                                     intermediate  resistant  sensitive    freq      sari
specimen_code microorganism_code antimicrobial_code
URICUL        ECOL               A_CEFPODOX                   0.0      595.0     8582.0  9177.0  0.064836
                                 ANIT                         0.0      347.0     8826.0  9173.0  0.037828
                                 ACELX                        0.0      803.0     8370.0  9173.0  0.087540
                                 ATRI                         0.0     3231.0     5941.0  9172.0  0.352268
                                 ACIP                         0.0     1259.0     7913.0  9172.0  0.137266
                                 AAUG                         0.0      602.0     8561.0  9163.0  0.065699
WOUCUL        SAUR               AFUS                         0.0      613.0     3631.0  4244.0  0.144439
                                 APEN                         0.0     3677.0      566.0  4243.0  0.866604
                                 AERY                         0.0     1186.0     3056.0  4242.0  0.279585
                                 AMET                         0.0      869.0     3372.0  4241.0  0.204905
Let’s choose the tuples were are interested in.
388 # -------------------------------------------
389 # Filter data
390 # -------------------------------------------
391 # Define spec, orgs, abxs of interest
392 spec = ['URICUL']
393 orgs = ['ECOL']
394 abxs = ['ACELX', 'ACIP', 'AAMPC', 'ATRI', 'AAUG',
395         'AMER', 'ANIT', 'AAMI', 'ACTX', 'ATAZ',
396         'AGEN', 'AERT', 'ACAZ', 'AMEC', 'ACXT']
397
398 # Create auxiliary DataFrame
399 aux = data.copy(deep=True) \
400
401 # Filter
402 idxs_spec = data.specimen_code.isin(spec)
403 idxs_orgs = data.microorganism_code.isin(orgs)
404 idxs_abxs = data.antimicrobial_code.isin(abxs)
405
406 # Filter
407 aux = aux[idxs_spec & idxs_orgs & idxs_abxs]
Now, lets compute the resistance trend.
414 # Libraries
415 import warnings
416
417 # Import specific libraries
418 from pyamr.core.sart import SART
419
420 # Variables
421 shift, period = '10D', '180D'
422
423 # Create instance
424 sar = SART(column_specimen='specimen_code',
425            column_microorganism='microorganism_code',
426            column_antimicrobial='antimicrobial_code',
427            column_date='date_received',
428            column_outcome='sensitivity',
429            column_resistance='sari')
430
431 with warnings.catch_warnings():
432     warnings.simplefilter('ignore')
433
434     # Compute resistance trends
435     table, objs = sar.compute(aux, shift=shift,
436         period=period, return_objects=True)
 1/15. Computing... ('URICUL', 'ECOL', 'AAMI')
 2/15. Computing... ('URICUL', 'ECOL', 'AAMPC')
 3/15. Computing... ('URICUL', 'ECOL', 'AAUG')
 4/15. Computing... ('URICUL', 'ECOL', 'ACAZ')
 5/15. Computing... ('URICUL', 'ECOL', 'ACELX')
 6/15. Computing... ('URICUL', 'ECOL', 'ACIP')
 7/15. Computing... ('URICUL', 'ECOL', 'ACTX')
 8/15. Computing... ('URICUL', 'ECOL', 'ACXT')
 9/15. Computing... ('URICUL', 'ECOL', 'AERT')
10/15. Computing... ('URICUL', 'ECOL', 'AGEN')
11/15. Computing... ('URICUL', 'ECOL', 'AMEC')
12/15. Computing... ('URICUL', 'ECOL', 'AMER')
13/15. Computing... ('URICUL', 'ECOL', 'ANIT')
14/15. Computing... ('URICUL', 'ECOL', 'ATAZ')
15/15. Computing... ('URICUL', 'ECOL', 'ATRI')
Lets see the results(note it is transposed!)
442 # Configure pandas
443 pd.set_option(
444     'display.max_colwidth', 20,
445     'display.width', 1000
446 )
447
448 # Show
449 #print("Results:")
450 #print(table.T)
451 table.head(4).T
Lets visualise the first entry
457 # Display
458 # This example shows how to make predictions using the wrapper and how
459 # to plot the result in data. In addition, it compares the intervals
460 # provided by get_prediction (confidence intervals) and the intervals
461 # provided by wls_prediction_std (prediction intervals).
462
463 # Variables
464 name, obj = objs[2] # AAUG
465
466 # Series
467 series = obj.as_series()
468
469 # Variables.
470 start, end = None, 50
471
472 # Get x and y
473 x = series['wls-exog'][:,1]
474 y = series['wls-endog']
475
476 # Compute predictions (exogenous?). It returns a 2D array
477 # where the rows contain the time (t), the mean, the lower
478 # and upper confidence (or prediction?) interval.
479 preds = obj.get_prediction(start=start, end=end)
480
481 # Create figure
482 fig, ax = plt.subplots(1, 1, figsize=(11, 5))
483
484 # Plotting confidence intervals
485 # -----------------------------
486 # Plot truth values.
487 ax.plot(x, y, color='#A6CEE3', alpha=0.5, marker='o',
488         markeredgecolor='k', markeredgewidth=0.5,
489         markersize=5, linewidth=0.75, label='Observed')
490
491 # Plot forecasted values.
492 ax.plot(preds[0, :], preds[1, :], color='#FF0000', alpha=1.00,
493         linewidth=2.0, label=obj._identifier(short=True))
494
495 # Plot the confidence intervals.
496 ax.fill_between(preds[0, :], preds[2, :],
497                 preds[3, :],
498                 color='r',
499                 alpha=0.1)
500
501 # Legend
502 plt.legend()
503 plt.title(name)

Text(0.5, 1.0, "('URICUL', 'ECOL', 'AAUG')")
Lets see the summary
508 # Summary
509 print("Name: %s\n" % str(name))
510 print(obj.as_summary())
Name: ('URICUL', 'ECOL', 'AAUG')
                            WLS Regression Results
==============================================================================
Dep. Variable:                      y   R-squared:                       0.906
Model:                            WLS   Adj. R-squared:                  0.904
Method:                 Least Squares   F-statistic:                     339.1
Date:                Thu, 15 Jun 2023   Prob (F-statistic):           1.38e-19
Time:                        18:15:41   Log-Likelihood:                   -inf
No. Observations:                  37   AIC:                               inf
Df Residuals:                      35   BIC:                               inf
Df Model:                           1
Covariance Type:            nonrobust
==============================================================================
                 coef    std err          t      P>|t|      [0.025      0.975]
------------------------------------------------------------------------------
const          1.5450      0.235      6.578      0.000       1.068       2.022
x1             0.1679      0.009     18.416      0.000       0.149       0.186
==============================================================================
Omnibus:                        5.037   Durbin-Watson:                   0.176
Prob(Omnibus):                  0.081   Jarque-Bera (JB):                2.336
Skew:                           0.316   Prob(JB):                        0.311
Kurtosis:                       1.944   Cond. No.                         91.7
Normal (N):                    21.394   Prob(N):                         0.000
==============================================================================
Lets display the information as a table graph for all tuples
516 # Libraries
517 from pyamr.graphics.table_graph import _DEFAULT_CONFIGURATION
518 from pyamr.graphics.table_graph import vlinebgplot
519
520 # Configuration for display
521 info = _DEFAULT_CONFIGURATION
522
523 # Lets define one as an example.
524 info['freq'] = {
525     'cmap': 'Blues',
526     'title': 'Freq',
527     'xticks': [0, 8000],
528     'kwargs': {
529         's': 80,
530         'vmin': 0
531     }
532 }
533
534 # .. note: It is important to ensure that the column names
535 #          match with the keys of the previously loaded
536 #          info configuration so that it is used.
537
538 # Rename columns
539 rename = {
540     'wls-x1_coef': 'sart_m',
541     'wls-const_coef': 'offset',
542     'wls-rsquared': 'r2',
543     'wls-rsquared_adj': 'r2_adj',
544     'wls-m_skew': 'skew',
545     'wls-m_kurtosis': 'kurtosis',
546     'wls-m_jb_prob': 'jb',
547     'wls-m_dw': 'dw',
548     'wls-const_tprob': 'ptm',
549     'wls-x1_tprob': 'ptn',
550     'wls-pearson': 'pearson',
551     'freq': 'freq',
552 }
553
554
555 # ----------------
556 # Combine with SARI
557
558 # Format combined DataFrame
559 comb = table.join(sari_overall)
560 comb.index = comb.index.map('_'.join)
561 comb = comb.reset_index()
562 comb = comb.rename(columns=rename)
563
564 # Add new columns
565 comb['sart_y'] = comb.sart_m * 12   # Yearly trend
566 comb['sari_pct'] = comb.sari * 100  # SARI percent
567
568 # Sort by trend
569 comb = comb.sort_values(by='sart_y', ascending=False)
570
571 # Select only numeric columns
572 # data = comb.select_dtypes(include=np.number)
573 data = comb[[
574     'index',
575     'sart_m',
576     #'sart_y',
577     'sari_pct',
578     'r2',
579     #'r2_adj',
580     'skew',
581     'kurtosis',
582     'jb',
583     'dw',
584     'ptm',
585     #'ptn',
586     'pearson',
587     'freq'
588 ]]
589
590 # Show DataFrame
591 #print("\nResults:")
592 #print(data)
593
594 # Create pair grid
595 g = sns.PairGrid(data, x_vars=data.columns[1:],
596     y_vars=["index"], height=3, aspect=.45)
597
598 # Set common features
599 g.set(xlabel='', ylabel='')
600
601 # Plot strips and format axes (skipping index)
602 for ax, c in zip(g.axes.flat, data.columns[1:]):
603
604     # Get information
605     d = info[c] if c in info else {}
606
607     # .. note: We need to use scatter plot if we want to
608     #          assign colors to the markers according to
609     #          their value.
610
611     # Using scatter plot
612     sns.scatterplot(data=data, x=c, y='index', s=100,
613                     ax=ax, linewidth=0.75, edgecolor='gray',
614                     c=data[c], cmap=d.get('cmap', None),
615                     norm=d.get('norm', None))
616
617     # Plot vertical lines
618     for e in d.get('vline', []):
619         vlinebgplot(ax, top=data.shape[0], **e)
620
621     # Configure axes
622     ax.set(title=d.get('title', c),
623            xlim=d.get('xlim', None),
624            xticks=d.get('xticks', []),
625            xlabel='', ylabel='')
626     ax.tick_params(axis='y', which='both', length=0)
627     ax.xaxis.grid(False)
628     ax.yaxis.grid(visible=True, which='major',
629                   color='gray', linestyle='-', linewidth=0.35)
630
631 # Despine
632 sns.despine(left=True, bottom=True)
633
634 # Adjust layout
635 plt.tight_layout()
636 plt.show()
637
638 #%
639 # Lets see the data plotted
640 data.round(decimals=3)
Computing ACSI
Warning
Pending…
Computing DRI
Warning
Pending…
Total running time of the script: ( 0 minutes 6.004 seconds)