Skip to contents

Calculates the single-day MME and total MME for each individual prescription opioid medication submitted for calculation. Also calculates total MME, total days of supply, and four distinct Total MME/Day calculations from the NIH HEAL Online MME Calculator across all prescription medications for two different medication groupings: 1) opioids without buprenorphine and 2) opioids with buprenorphine.

Usage

# S3 method for class 'data.frame'
calculate_mme(
  x,
  id_col = "patient_id",
  medication_col = "medication_name",
  dose_col = "dose",
  doses_per_day_col = "doses_per_24_hours",
  days_col = "days_of_medication",
  therapy_days_col = "therapy_days",
  observation_days_col = "observation_window_days",
  therapy_days_without_col = NULL,
  observation_days_without_col = NULL,
  use_api = FALSE,
  ...
)

# S3 method for class 'tbl_df'
calculate_mme(
  x,
  id_col = "patient_id",
  medication_col = "medication_name",
  dose_col = "dose",
  doses_per_day_col = "doses_per_24_hours",
  days_col = "days_of_medication",
  therapy_days_col = "therapy_days",
  observation_days_col = "observation_window_days",
  therapy_days_without_col = NULL,
  observation_days_without_col = NULL,
  use_api = FALSE,
  ...
)

Arguments

x

(data.frame or tbl_df)
Object with input data - either a data.frame or tibble with data in long format, with one row per medication per patient or participant (id_col) and including all necessary data for MME calculations (see opioid_trial data) and/or other function arguments

id_col

(charcter)
Name of the column containing patient identifier; default is "patient_id"

medication_col

(charcter)
Name of the column containing medication names; default is "medication_name"

dose_col

(charcter)
Name of the column containing dose values; default is "dose"

doses_per_day_col

(charcter)
Name of the column containing doses per 24 hours; default is "doses_per_24_hours"

days_col

(charcter)
Name of the column containing days of medication; default is "days_of_medication"

therapy_days_col

(charcter)
Name of the column containing therapy days with buprenorphine (up to one unique value per patient); default is "therapy_days"

observation_days_col

(charcter)
Name of the column containing observation window days with buprenorphine (up to one unique value per patient); default is "observation_window_days"

therapy_days_without_col

(charcter)
Name of the column containing therapy days without buprenorphine (up to one unique value per patient). If NULL (default), uses the value from therapy_days_col.

observation_days_without_col

(charcter)
Name of the column containing observation window days without buprenorphine (up to one unique value per patient). If NULL (default), uses the value from observation_days_col.

use_api

(logical)
Indicates whether to use the NIH HEAL Online MME Calculator API to perform calculations or perform them locally instead. For calculate_mme.data.frame() and calculate_mme.tbl_df(), the default is FALSE, as the functions assume the user needs to perform the MME calculations without being restricted by the API rate limit of 50 patient-level calculations per 15 minutes. This also allows the user to perform the calculations without relying on internet access.

...

These dots are for future extensions and must be empty.

Value

A list containing three data.frame elements:

  • medications: The original data with added prescription-level MME columns

  • patient_summary_with_buprenorphine: Patient-level MME summary including buprenorphine

  • patient_summary_without_buprenorphine: Patient-level MME summary excluding buprenorphine

Details

The function will provide the same results regardless of whether the user has specified they want calculation done using the API (use_api). Specifying use_api == FALSE helps overcome the online calculator API rate limit of 50 (patient-level) requests per 15 minutes. In addition to returning user-specified arguments, calculate_mme() also returns several other variables mentioned in the Description section. Output variable description details are below; see Adams, et al. (2025) for a comprehensive overview.

Prescription-Level

Conversion Factor for <medication_name> (factor): the conversion factor used for calculating total MME/day.

MME for <medication_name> (mme): Morphine milligram equivalent for the whole prescription specified in medication_name, calculated as (dose) * (doses_per_24_hours) * (factor) * (days_of_medication).

24h MME for <medication_name> (single_day_mme): Morphine milligram equivalent for the prescription specified in medication_name for a single day, calculated as (dose) * (doses_per_24_hours) * (factor).

One day: Typically, the day with highest opioid exposure is entered, and the sum of 24-hour MME across the drugs that apply to this day is calculated. Highest MME in one day is definition 4.

Summary-Level:

On-therapy Days (therapy_days): The sum of prescription duration (days_of_medication) for each medication, but with each calendar day counted only ONCE. User-supplied; this is the denominator for MME/Day definition 2.

  • If there is only one prescription, or if there is no calendar overlap (no days on which more than one prescription is active), this will be the same as the total days supply.

  • If there are overlapping prescriptions, this is the number of unique calendar days.

Total MME (total_mme): The MME for each medication, summed across all prescriptions. This is the numerator for MME/Day definitions 1, 2, and 3.

Total Days Supply (total_days): The sum of the entered prescription duration (days_of_medication) for each of the medications (Med 1 duration + med 2 duration...). Automatically calculated. This is the denominator for MME/Day definition 1.

MME/Day

MME/Day is an aggregate measure, calculating the total MME divided by a specified time window (a number of days). The MME/Day definitions specify the number of days:

MME/Day Definition 1 (mme1): Total Days Supply

MME Definition 1 = Total MME / Total Days Supply time window (sum of entered prescription durations).

mme1 = total_mme / total_days

  • Note that the same calendar day may contribute multiple times, if overlapping prescriptions.

  • Reason to select this definition: This is the least complicated calculation; appears best suited when immediate-release opioids are prescribed for short discrete times.

  • Identified challenge with this definition: It consistently underestimated MME per day when overlapping prescriptions were present or when immediate-release and extended release opioids were prescribed concurrently.

MME/Day Definition 2 (mme2): On-therapy Days

MME Definition 2 = Total MME / On-therapy Days time window (sum of entered prescription durations except each calendar day is counted only ONCE).

mme2 = total_mme / therapy_days

  • Note - On-therapy Days unique calendar days.

  • Reason to select this definition: Provides a smoothed measure useful in studies of dose-dependent adverse effects, including opioid-induced constipation or overdose in patients with opioid tolerance or who have been stable on opioids.

  • Identified challenge with this definition: The metric is time-varying and affords the greatest flexibility to define medication gap periods and leftover/unused medications to improve pharmacoepidemiologic studies.

MME/Day Definition 3 (mme3): Fixed Observation Window

Uses the Total MME study-specified fixed observation window. MME Definition 3 = Total MME / Number of days in observation window:

mme3 = total_mme / observation_window_days

  • If this definition is selected, it is important to report on the duration of the fixed window.

  • Reason to select this definition: Most suitable for studies with a known or suspected duration of risk during which adverse events are expected to occur, such as incidence of opioid use disorder. This definition may be useful when prescriptions are filled at irregular time intervals on a as needed basis (pro re nata, PRN).

  • Identified challenge with this definition: The definition consistently had the lowest milligrams per day for immediate-release opioids. It is the most robust to misspecification, amenable to transformations, and has the least noise when constructing continuous functions. However, since it assumes uniform exposure/risk within a window, there is less scope for time-varying adjustment.

  • This is the definition recommended by the Department of Health and Human Services Office of the Inspector General.

MME/Day Definition 4 (mme4): Maximum Daily Dose

Uses the sum of 24-hour MME for the day with highest opioid exposure.

MME Definition 4 = Drug 1 (dose (mg) x # of doses per day) x conversion factor + Drug 2 (dose (mg) x # of doses per day) x conversion factor + ...

mme4 = sum(dose * doses_per_24_hours * factor)

  • Report the highest single-day exposure.

  • Reason to select this definition: A toxicological perspective may be appropriate for patients with no opioid tolerance and in the presence of comorbidities for respiratory depression. It appears to be best suited for immediate dose-dependent toxic effects, such as respiratory depression.

  • Identified challenged with this definition: This definition may have limited use if it includes opioids where fatal toxicity does not involve respiratory depression (e.g., tramadol) or have atypical mu-opioid receptor agonism (e.g., tapentadol, buprenorphine).

  • The definition assumes uniform risk of adverse outcomes regardless of time on-therapy. More so than the others, this definition is prone to influence from early refills, unused medication, and how the 90 MME threshold is operationalized.

  • This definition underlies the algorithm embedded in the CDC Opioid Guideline mobile app. There may be difficulty reconciling findings with studies using the other definitions because it returns a MME per day that is significantly higher.

  • This calculator sums the 24-hour MME for every prescription, without considering calendar dates.

Examples

library(dplyr)
#> 
#> Attaching package: ‘dplyr’
#> The following objects are masked from ‘package:stats’:
#> 
#>     filter, lag
#> The following objects are masked from ‘package:base’:
#> 
#>     intersect, setdiff, setequal, union
# Calculate MME using long-format data
# Subset of opioid_trial data used for speedier example
mme <- calculate_mme(
  x = opioid_trial |> dplyr::filter(patient_id %in% sprintf("P%03d", 1:100)),
  therapy_days_without_col = "therapy_days_without",
  observation_days_without_col = "observation_window_days_without"
  )

head(mme$medications)
#> # A tibble: 6 × 12
#>   patient_id medication_name          dose doses_per_24_hours days_of_medication
#>   <chr>      <chr>                   <dbl>              <dbl>              <dbl>
#> 1 P001       Fentanyl patch (mcg/hr)  12.5                  1                  7
#> 2 P001       tramadol (mg) LA        125                    1                 30
#> 3 P002       Hydrocodone (mg)         10                    3                 14
#> 4 P002       tramadol (mg)            60                    3                 14
#> 5 P003       Meperidine HCL (mg)      50                    4                  7
#> 6 P003       tramadol (mg)            90                    3                  7
#> # ℹ 7 more variables: therapy_days <dbl>, observation_window_days <dbl>,
#> #   therapy_days_without <dbl>, observation_window_days_without <dbl>,
#> #   factor <dbl>, mme <dbl>, single_day_mme <dbl>

head(mme$patient_summary_with_buprenorphine)
#>   patient_id therapy_days observation_window_days total_mme total_days
#> 1       P001            7                      30    960.00         37
#> 2       P002           14                      30    924.00         28
#> 3       P003            7                      30   2228.00         31
#> 4       P004            7                      30    210.00          7
#> 5       P005            7                      30     47.25          7
#> 6       P006            7                      30   3395.25         31
#>        mme1     mme2      mme3   mme4
#> 1  25.94595 137.1429  32.00000  55.00
#> 2  33.00000  66.0000  30.80000  66.00
#> 3  71.87097 318.2857  74.26667 204.00
#> 4  30.00000  30.0000   7.00000  30.00
#> 5   6.75000   6.7500   1.57500   6.75
#> 6 109.52419 485.0357 113.17500 393.75

head(mme$patient_summary_without_buprenorphine)
#>   patient_id therapy_days observation_window_days total_mme total_days
#> 1       P001            7                      30    960.00         37
#> 2       P002           14                      30    924.00         28
#> 3       P003            7                      30   2228.00         31
#> 4       P004            7                      30    210.00          7
#> 5       P005            7                      30     47.25          7
#> 6       P006            7                      30   3395.25         31
#>        mme1     mme2      mme3   mme4
#> 1  25.94595 137.1429  32.00000  55.00
#> 2  33.00000  66.0000  30.80000  66.00
#> 3  71.87097 318.2857  74.26667 204.00
#> 4  30.00000  30.0000   7.00000  30.00
#> 5   6.75000   6.7500   1.57500   6.75
#> 6 109.52419 485.0357 113.17500 393.75

# Cleanup
rm(mme)