* mdro(): infer base drug resistance from drug+inhibitor combination columns (#209) When a base beta-lactam column (e.g., piperacillin/PIP) is absent but a corresponding drug+inhibitor combination (e.g., piperacillin/tazobactam/TZP) is present and resistant, resistance in the base drug is now correctly inferred. This is clinically sound: resistance in a combination implies the inhibitor provided no benefit, so the base drug is also resistant. Susceptibility in a combination is NOT propagated to the base drug (the inhibitor may be responsible for susceptibility), so only R values are inferred; missing base drugs remain NA otherwise. Implementation details: - Uses AB_BETALACTAMS_WITH_INHIBITOR to identify all beta-lactam+inhibitor combinations present in the user's data - Derives base drug AB codes by stripping the "/inhibitor" part from names - Creates synthetic proxy columns (.sir_proxy_<AB>) in x, set to "R" when any matching combination is R, otherwise NA - Proxy columns are added to cols_ab before drug variable assignment, so all existing guideline logic benefits without any changes - Multiple combos for the same base drug are OR-ed (any R → R) - Adds internal ab_without_inhibitor() helper for the name->base mapping - Verbose mode reports which combinations are used for inference Bumps version: 3.0.1.9028 -> 3.0.1.9029 https://claude.ai/code/session_01Cp154UtssHg84bw38xiiTG * Add sir.R/mic.R fixes and mdro() unit tests; bump to 3.0.1.9030 R/sir.R (line 571): Guard purely numeric strings (e.g. "1", "8") from the Unicode letter filter. Values matching the broad SIR regex but consisting only of digits must not be stripped; add `x %unlike% "^[0-9+]$"` predicate. R/mic.R (lines 220-222): Preserve the letter 'e' during Unicode-letter removal so that MIC values in scientific notation (e.g. "1e-3", "2.5e-2") survive the cleaning step. - Line 220: [\\p{L}] → [^e\\P{L}] (remove all letters except 'e') - Line 222: [^0-9.><= -]+ → [^0-9e.><= -]+ (allow 'e' in whitelist) tests/testthat/test-mdro.R: New tests for the drug+inhibitor inference added in the previous commit (issue #209): - TZP=R with no PIP column → PIP inferred R → MDRO class elevated - TZP=S with no PIP column → proxy col is NA (not S) → class lower - verbose mode emits "Inferring resistance" message - AMC=R with no AMX column runs without error (Enterococcus faecium) https://claude.ai/code/session_01Cp154UtssHg84bw38xiiTG * Fix version to single bump (9029) and update CLAUDE.md versioning rules CLAUDE.md: Rewrite the "Version and date bump" subsection to document that: - Exactly ONE version bump is allowed per PR (PRs are squash-merged into one commit on the default branch, so one commit = one version increment) - The correct version is computed from git history: currentversion="${currenttag}.$((commits_since_tag + 9001 + 1))" with the +1 accounting for the PR's own squash commit not yet on the default branch - Fall back to incrementing DESCRIPTION's version by 1 if git describe fails - The Date: field tracks the date of the *last* PR commit (updated each time) DESCRIPTION / NEWS.md: Correct the version from 3.0.1.9030 back to 3.0.1.9029. Two version bumps were made across two commits in this PR; since it will be squash-merged as one commit only one bump is correct. Also update Date to today (2026-03-07). https://claude.ai/code/session_01Cp154UtssHg84bw38xiiTG * Fix stats::setNames, test accessor bug, and version script verification R/mdro.R: Qualify setNames() as stats::setNames() in the drug+inhibitor inference block to satisfy R CMD CHECK's global-function checks. tests/testthat/test-mdro.R: mdro() with verbose=FALSE returns an atomic ordered factor, not a data.frame. Fix three test errors introduced in the previous commit: - Line 320: result_no_pip$MDRO -> result_no_pip (factor, no $ accessor) - Line 328: result_tzp_s$MDRO / result_no_pip$MDRO -> direct factor refs - Line 347: expect_inherits(..., "data.frame") -> c("factor","ordered") Also fix the comment on line 347 to match the actual return type. Version: confirmed at 3.0.1.9029 (no further bump; one bump already made this PR). git describe failed (no tags in dev environment) — fallback applies. The +1 in CLAUDE.md's formula is correct for tagged repos: currentcommit + 9001 + 1 = 27 + 9001 + 1 = 9029 ✓ https://claude.ai/code/session_01Cp154UtssHg84bw38xiiTG * Fix unit tests: use mrgn guideline and expect_message() for proxy tests Three failures corrected: 1. Classification tests (lines 321, 329): The EUCAST guideline for P. aeruginosa already has OR logic (PIP OR TZP), so TZP=R alone satisfies it regardless of whether the PIP proxy exists. Switch to guideline="mrgn": the MRGN 4MRGN criterion for P. aeruginosa requires PIP=R explicitly (lines 1488-1496 of mdro.R), with no TZP fallback. Without the proxy: PIP missing -> not 4MRGN -> level 1. With the proxy (TZP=R infers PIP=R): 4MRGN reached -> level 3. The TZP=S case leaves proxy=NA, so PIP is still absent effectively -> level 1, which is < level 3 as expected. 2. Verbose/message test (line 335): message_() routes through message() to stderr, not cat() to stdout. expect_output() only captures stdout so it always saw nothing. Fix: use expect_message() instead, and remove the inner suppressMessages() that was swallowing the message before expect_message() could capture it. Also trim two stale lines left over from the old expect_output block. https://claude.ai/code/session_01Cp154UtssHg84bw38xiiTG --------- Co-authored-by: Claude <noreply@anthropic.com>
The AMR Package for R
Please visit our comprehensive package website https://amr-for-r.org to read more about this package, including many examples and tutorials.
Overview:
- Provides an all-in-one solution for antimicrobial resistance (AMR) data analysis in a One Health approach
- Peer-reviewed, used in over 175 countries, available in 28 languages
- Generates antibiograms - traditional, combined, syndromic, and even WISCA
- Provides the full microbiological taxonomy of ~79 000 distinct species and extensive info of ~620 antimicrobial drugs
- Applies CLSI 2011-2025 and EUCAST 2011-2025 clinical and veterinary breakpoints, and ECOFFs, for MIC and disk zone interpretation
- Corrects for duplicate isolates, calculates and predicts AMR per antimicrobial class
- Integrates with WHONET, ATC, EARS-Net, PubChem, LOINC, SNOMED CT, and NCBI
- 100% free of costs and dependencies, highly suitable for places with limited resources
The AMR package is a peer-reviewed, free and open-source R package
with zero dependencies to simplify the analysis and prediction of
Antimicrobial Resistance (AMR) and to work with microbial and
antimicrobial data and properties, by using evidence-based methods.
Our aim is to provide a standard for clean and reproducible AMR data
analysis, that can therefore empower epidemiological analyses to
continuously enable surveillance and treatment evaluation in any
setting.
The AMR package supports and can read any data format, including
WHONET data. This package works on Windows, macOS and Linux with all
versions of R since R-3.0 (April 2013). It was designed to work in any
setting, including those with very limited resources. It was created
for both routine data analysis and academic research at the Faculty of
Medical Sciences of the University of Groningen
and the University Medical Center Groningen.
How to get this package
To install the latest ‘release’ version from CRAN:
install.packages("AMR")
To install the latest ‘beta’ version:
install.packages("AMR", repos = "beta.amr-for-r.org")
If this does not work, try to install directly from GitHub using the
remotes package:
remotes::install_github("msberends/AMR")
This AMR package for R is free, open-source software and licensed under the GNU General Public License v2.0 (GPL-2). These requirements are consequently legally binding: modifications must be released under the same license when distributing the package, changes made to the code must be documented, source code must be made available when the package is distributed, and a copy of the license and copyright notice must be included with the package.