| Title: | Tools for Working with Hospital Readmissions Data |
|---|---|
| Description: | Contains tools for working with and analyzing hospital readmissions data. The package provides utilities for components of the Hospital Readmissions Reduction Program (HRRP), including program timeline functions, Hospital-Specific Report (HSR) helpers, and general importing tools for the Provider Data Catalog (PDC). |
| Authors: | Alex Zajichek [aut, cre, cph] |
| Maintainer: | Alex Zajichek <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.0.1.9000 |
| Built: | 2026-05-28 06:44:41 UTC |
| Source: | https://github.com/centralstatz/readmit |
Identifies key dates (see hrrp_keydates) from the Hospital Readmissions Reduction Program (HRRP) that are associated with an input reference date, such as performance and payment periods.
hrrp_get_dates(ref, period = c("payment", "performance"), discharge = TRUE)hrrp_get_dates(ref, period = c("payment", "performance"), discharge = TRUE)
ref |
A |
period |
The program period to extract dates for. One of |
discharge |
Should the |
my_date <- as.Date("2022-01-01") # What are the payment periods for this discharge? hrrp_get_dates(my_date, period = "payment", discharge = TRUE) # What performance periods is this discharge included in? hrrp_get_dates(my_date, period = "performance", discharge = TRUE) # What is the payment period overlapping this date? hrrp_get_dates(my_date, period = "payment", discharge = FALSE) # What is the performance period whose penalty period overlaps this date? hrrp_get_dates(my_date, period = "performance", discharge = FALSE) # What is the performance period for current penalty enforcement? hrrp_get_dates(Sys.Date(), period = "performance", discharge = FALSE)my_date <- as.Date("2022-01-01") # What are the payment periods for this discharge? hrrp_get_dates(my_date, period = "payment", discharge = TRUE) # What performance periods is this discharge included in? hrrp_get_dates(my_date, period = "performance", discharge = TRUE) # What is the payment period overlapping this date? hrrp_get_dates(my_date, period = "payment", discharge = FALSE) # What is the performance period whose penalty period overlaps this date? hrrp_get_dates(my_date, period = "performance", discharge = FALSE) # What is the performance period for current penalty enforcement? hrrp_get_dates(Sys.Date(), period = "performance", discharge = FALSE)
A collection of datasets giving important dates involved in the Hospital Readmissions Reduction Program (HRRP), including performance periods, payment periods, review and correction periods, claims snapshot dates, and cohort inclusion status for program years since 2019. The data is manually abstracted from QualityNet and was most recently updated on 11/21/2025.
All tables contain the ProgramYear, which is the HRRP program (or federal fiscal year) in question.
Tables with date ranges contain a StartDate and EndDate contain the beginning and end dates of the
respective interval. Other tables contain individual dates or indicators for cohort inclusion (see descriptions).
hrrp_keydates hrrp_performance_periods hrrp_payment_periods hrrp_review_periods hrrp_snapshot_dates hrrp_cohort_inclusionhrrp_keydates hrrp_performance_periods hrrp_payment_periods hrrp_review_periods hrrp_snapshot_dates hrrp_cohort_inclusion
hrrp_performance_periodsStart and end dates for discharges evaluated for readmissions. Note some program years have multiple performance intervals and are represented on separate rows of this table.
hrrp_payment_periodsStart and end dates for when payment penalties are applied by CMS to hospital reimbursement.
hrrp_review_periodsStart and end dates for the review and correction period where hospitals could review discharge-level data and downstream calculations of penalty amounts.
hrrp_snapshot_datesThe as of date for when claims data were extracted by CMS for evaluation in the program. Note some discrepancies exist in CMS documentation for these dates (e.g., FY2026) when comparing anticipated versus actual snapshot date. The latter was used in this case.
hrrp_cohort_inclusionIndicators of whether each cohort was included in the program for the given year. 1 = included, 0 = excluded.
Acute Myocardial Infarction
Chronic Obstructive Pulmonary Disease
Heart Failure
Pneumonia
Coronary Artery Bypass Graft
Total Hip/Knee Replacement
hrrp_keydatesA combined table that joins all of the above individual tables into a single common table with altered column names.
An object of class tbl_df (inherits from tbl, data.frame) with 11 rows and 3 columns.
An object of class tbl_df (inherits from tbl, data.frame) with 9 rows and 3 columns.
An object of class tbl_df (inherits from tbl, data.frame) with 8 rows and 3 columns.
An object of class tbl_df (inherits from tbl, data.frame) with 9 rows and 2 columns.
An object of class tbl_df (inherits from tbl, data.frame) with 9 rows and 7 columns.
https://qualitynet.cms.gov/inpatient/hrrp/resources#tab1
Extracts the regression coefficients from the parsed HSR coefficients
component for a given cohort.
hsr_coefficients(file, cohort)hsr_coefficients(file, cohort)
file |
A parsed HSR bundle or a local source bundle path. |
cohort |
Cohort to extract the coefficients for. One of |
A tibble::tibble() containing the columns:
Factor: The model term name (as listed in the file)
Value: The model coefficient value (on the linear predictor scale)
bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), term = c("AGE", "HOSP_EFFECT"), value = c(0.25, -0.10) ), file.path(bundle_path, "coefficients.csv"), row.names = FALSE ) hsr_coefficients(bundle_path, "HF")bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), term = c("AGE", "HOSP_EFFECT"), value = c(0.25, -0.10) ), file.path(bundle_path, "coefficients.csv"), row.names = FALSE ) hsr_coefficients(bundle_path, "HF")
Extracts cohort summary information from the HSR, including (but not limited to) the discharge/readmission volumes, predicted/expected readmission rates, peer group medians, and DRG ratios.
Note: CMS changed the format of Hospital-Specific Reports (HSRs) for FY2026 (see here). The current HSR functions support formats through FY2025.
hsr_cohort_summary(file)hsr_cohort_summary(file)
file |
A parsed HSR bundle, a local source bundle path, or a legacy file path. |
A tibble::tibble() containing the full Table 2 parsed from the report.
# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Extract the cohort summary as a dataset hsr_cohort_summary(my_report)# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Extract the cohort summary as a dataset hsr_cohort_summary(my_report)
Detects the broad file format of a Hospital-Specific Report (HSR). Phase 1 only recognizes the legacy Excel-based format used through FY2025.
hsr_detect_format(path)hsr_detect_format(path)
path |
File path to a report. |
A scalar character string describing the detected format.
report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") hsr_detect_format(report)report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") hsr_detect_format(report)
Extracts discharge-level data for a specific cohort from a parsed HSR bundle.
hsr_discharges( file, cohort, discharge_phi = TRUE, risk_factors = FALSE, eligible_only = FALSE )hsr_discharges( file, cohort, discharge_phi = TRUE, risk_factors = FALSE, eligible_only = FALSE )
file |
A parsed HSR bundle or a local source bundle path. |
cohort |
Cohort to extract the discharges for. One of |
discharge_phi |
Should discharge PHI be included? Defaults to |
risk_factors |
Should readmission risk factors be included? Defaults to |
eligible_only |
Should only eligible discharges be included? Defaults to |
Parsed discharge components must already have any file-structure differences
resolved upstream by the parser layer. This helper operates only on the
conceptual discharges component in the parsed bundle.
eligible_only = TRUE is supported when the parsed component contains one or
more cohort inclusion columns. The discharge_phi and risk_factors
arguments currently only support the default behavior
(discharge_phi = TRUE, risk_factors = FALSE); other combinations fail
clearly until richer discharge field metadata is available in parsed bundles.
bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), `ID Number` = c(1001, 1002), index_stay = c(1, 1) ), file.path(bundle_path, "discharges.csv"), row.names = FALSE ) hsr_discharges(bundle_path, "HF")bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), `ID Number` = c(1001, 1002), index_stay = c(1, 1) ), file.path(bundle_path, "discharges.csv"), row.names = FALSE ) hsr_discharges(bundle_path, "HF")
Extracts the discharge-level records from the HSR of patients who were dually-eligible for Medicare and Medicaid benefits (see details).
Note: CMS changed the format of Hospital-Specific Reports (HSRs) for FY2026 (see here). The current HSR functions support formats through FY2025.
hsr_dual_stays(file)hsr_dual_stays(file)
file |
A parsed HSR bundle, a local source bundle path, or a legacy file path. |
In the Hospital Readmissions Reduction Program (HRRP), hospitals' readmission rates are compared against a peer group of "like" hospitals, which determines whether or not they will get penalized financially.
The peer group allocation done by CMS is determined by creating hospital groupings based
on the share of Medicare beneficiaries who were also eligible for Medicaid benefits, a marker of socioeconomic status
in the hospital population. hsr_dual_stays() extracts the list of discharges accounting for the numerator of this ratio.
# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Extract dually-eligible stays as a dataset hsr_dual_stays(my_report)# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Extract dually-eligible stays as a dataset hsr_dual_stays(my_report)
Provides the location of mock HSRs downloaded from QualityNet that come with the package that users can import. These files are a representation of what a hospital's real report looks like when received from CMS. They contain mock data for sensitive fields (discharge level data, etc.), but real data for national level results (e.g., model coefficients). Thus, it gives user ability to practice/explore package functions and translate them to their own hospital reports. Files include fiscal years (FY) 2019-2025 and were downloaded on 11/8/2025 from https://qualitynet.cms.gov/inpatient/hrrp/reports. File names were changed for better identifiability.
Note: CMS changed the format of Hospital-Specific Reports (HSRs) for FY2026 (see here). The current HSR functions support formats through FY2025.
hsr_mock_reports(path = NULL)hsr_mock_reports(path = NULL)
path |
Name of file. If NULL, all files will be listed. |
This function was adapted from readxl::readxl_example().
A character string or vector of strings
# Show all available mock reports hsr_mock_reports() # Show path to a single report hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Use mock report for testing package functions hsr_payment_summary(hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx"))# Show all available mock reports hsr_mock_reports() # Show path to a single report hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Use mock report for testing package functions hsr_payment_summary(hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx"))
Parses a local HSR source bundle into a lightweight conceptual bundle. The parsed bundle tracks component outputs separately from source artifacts and preserves artifact lineage and raw parser metadata.
hsr_parse(x, spec = hsr_parser_config(), ...)hsr_parse(x, spec = hsr_parser_config(), ...)
x |
A local HSR source bundle path or a |
spec |
A parser configuration created by |
... |
Reserved for future parser options. |
A readmit_hsr_bundle object.
bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame(metric = "payment_adjustment_factor", value = 0.98), file.path(bundle_path, "payment_summary.csv"), row.names = FALSE ) hsr_parse(bundle_path, spec = hsr_parser_config())bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame(metric = "payment_adjustment_factor", value = 0.98), file.path(bundle_path, "payment_summary.csv"), row.names = FALSE ) hsr_parse(bundle_path, spec = hsr_parser_config())
Creates a parser configuration object that controls how local HSR source bundles are interpreted. The package provides built-in defaults for file inclusion, artifact role hints, embedded component markers, and basic column aliases, while allowing users to override selected assumptions when their files differ.
hsr_parser_config(artifacts = NULL, components = NULL)hsr_parser_config(artifacts = NULL, components = NULL)
artifacts |
Optional artifact-level overrides. |
components |
Optional component-level overrides. |
A readmit_hsr_spec object.
spec <- hsr_parser_config() spec$artifacts$role_hints$payment_summary <- c("payment", "summary_table") specspec <- hsr_parser_config() spec$artifacts$role_hints$payment_summary <- c("payment", "summary_table") spec
Extracts payment summary information from the HSR, including (but not limited to) the payment penalty, peer group the hospital was compared against, and dual proportion that determines peer group assignment.
Note: CMS changed the format of Hospital-Specific Reports (HSRs) for FY2026 (see here). The current HSR functions support formats through FY2025.
hsr_payment_summary(file) hsr_count_dual_stays(file) hsr_count_total_stays(file) hsr_dual_proportion(file) hsr_peer_group(file) hsr_neutrality_modifier(file) hsr_payment_adjustment_factor(file) hsr_payment_penalty(file)hsr_payment_summary(file) hsr_count_dual_stays(file) hsr_count_total_stays(file) hsr_dual_proportion(file) hsr_peer_group(file) hsr_neutrality_modifier(file) hsr_payment_adjustment_factor(file) hsr_payment_penalty(file)
file |
A parsed HSR bundle, a local source bundle path, or a legacy file path. For convenience functions, this can also be the pre-parsed payment summary table itself (to minimize file I/O). |
hsr_payment_summary() returns a tibble::tibble() containing the full Table 1 parsed from the report.
Additional convenience functions extract specific columns from this table, and always return a numeric value.
# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Full payment summary table payment_summary <- hsr_payment_summary(my_report) payment_summary # Extract individual components (from file) hsr_payment_penalty(my_report) # Or existing extract hsr_payment_penalty(payment_summary)# Access a report my_report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") # Full payment summary table payment_summary <- hsr_payment_summary(my_report) payment_summary # Extract individual components (from file) hsr_payment_penalty(my_report) # Or existing extract hsr_payment_penalty(payment_summary)
Parses a Hospital-Specific Report (HSR) into a lightweight internal object that can be reused by downstream helpers. Phase 1 support is limited to the legacy Excel-based HSR format used through FY2025.
The parsed object preserves current legacy section outputs as much as possible, while also retaining raw parser metadata for debugging and future format support.
If format is left NULL, hsr_detect_format() is used to identify the
supported parser to apply.
hsr_read(path, format = NULL, validate = TRUE, ...)hsr_read(path, format = NULL, validate = TRUE, ...)
path |
File path to a report. |
format |
Optional format override. Defaults to |
validate |
Should the parsed object be validated before returning?
Defaults to |
... |
Reserved for future parser-specific options. |
A readmit_hsr object.
report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") parsed <- hsr_read(report) parsedreport <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") parsed <- hsr_read(report) parsed
Computes the predicted and expected readmission risks for each eligible discharge in the specified cohort from parsed HSR components.
hsr_readmission_risks(file, cohort)hsr_readmission_risks(file, cohort)
file |
A parsed HSR bundle or a local source bundle path. |
cohort |
Cohort to compute readmission risks for. One of |
The readmission measure is what CMS uses to grade performance in the Hospital Readmissions Reduction Program (HRRP).
Individual discharges are assigned an adjusted readmission risk (based on clinical history), which then get aggregated into a hospital-level score and compared to peer groups for penalty determination. Specifically, a random-intercept logistic regression model is built for each cohort (see methodology) which serves as the basis for two (2) readmission risks assigned to each discharge:
Predicted: Adjusted for patient-specific clinical factors plus the hospital-specific effect (random intercept term)
Expected: Adjusted for patient-specific clinical factors plus the hospital-average effect
These quantities are then aggregated across all discharges and their ratio is taken to form the Excess Readmission Ratio (ERR), which is then used as the cohort-specific comparison metric. Thus, it is a comparative measure of how likely patients are to be readmitted at your hospital versus the average hospital, given your hospital's clinical characteristics.
A tibble::tibble() containing the following columns:
ID Number: The unique discharge identifier (see hsr_discharges())
Predicted: The predicted readmission risk for the discharge
Expected: The expected readmission risk for the discharge
bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), `ID Number` = c(1001, 1002), AGE = c(1, 0) ), file.path(bundle_path, "discharges.csv"), row.names = FALSE ) utils::write.csv( data.frame( cohort = c("HF", "HF", "HF"), term = c("AGE", "HOSP_EFFECT", "AVG_EFFECT"), value = c(0.25, -0.10, -0.20) ), file.path(bundle_path, "coefficients.csv"), row.names = FALSE ) # Compute readmission risks for HF discharges hf_risks <- hsr_readmission_risks(bundle_path, "HF") hf_risks # Compute the ERR from scratch hf_risks |> dplyr::summarize( Discharges = dplyr::n(), Predicted = mean(Predicted), Expected = mean(Expected), ERR = Predicted / Expected )bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame( cohort = c("HF", "HF"), `ID Number` = c(1001, 1002), AGE = c(1, 0) ), file.path(bundle_path, "discharges.csv"), row.names = FALSE ) utils::write.csv( data.frame( cohort = c("HF", "HF", "HF"), term = c("AGE", "HOSP_EFFECT", "AVG_EFFECT"), value = c(0.25, -0.10, -0.20) ), file.path(bundle_path, "coefficients.csv"), row.names = FALSE ) # Compute readmission risks for HF discharges hf_risks <- hsr_readmission_risks(bundle_path, "HF") hf_risks # Compute the ERR from scratch hf_risks |> dplyr::summarize( Discharges = dplyr::n(), Predicted = mean(Predicted), Expected = mean(Expected), ERR = Predicted / Expected )
Resolves a local source bundle for Hospital-Specific Report (HSR) parsing. The returned object inventories source artifacts but does not parse them into conceptual components.
hsr_resolve_source(x, spec = hsr_parser_config(), ...)hsr_resolve_source(x, spec = hsr_parser_config(), ...)
x |
Path to a local HSR source bundle. |
spec |
A parser configuration created by |
... |
Reserved for future source-resolution options. |
A readmit_hsr_source object.
bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame(metric = "payment_adjustment_factor", value = 0.98), file.path(bundle_path, "payment_summary.csv"), row.names = FALSE ) hsr_resolve_source(bundle_path, spec = hsr_parser_config())bundle_path <- file.path(tempdir(), "hsr_bundle") dir.create(bundle_path, recursive = TRUE) utils::write.csv( data.frame(metric = "payment_adjustment_factor", value = 0.98), file.path(bundle_path, "payment_summary.csv"), row.names = FALSE ) hsr_resolve_source(bundle_path, spec = hsr_parser_config())
Check whether an object is a parsed HSR
is_hsr(x)is_hsr(x)
x |
An object to test. |
TRUE if x inherits from class \"readmit_hsr\", otherwise
FALSE.
report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") parsed <- hsr_read(report) is_hsr(parsed) is_hsr(report)report <- hsr_mock_reports("FY2025_HRRP_MockHSR.xlsx") parsed <- hsr_read(report) is_hsr(parsed) is_hsr(report)
Check whether an object is a parsed HSR bundle
is_hsr_bundle(x)is_hsr_bundle(x)
x |
An object to test. |
TRUE if x inherits from class \"readmit_hsr_bundle\",
otherwise FALSE.
Check whether an object is an HSR source bundle
is_hsr_source(x)is_hsr_source(x)
x |
An object to test. |
TRUE if x inherits from class \"readmit_hsr_source\",
otherwise FALSE.
Explore and import datasets directly from the CMS Provider Data Catalog (PDC).
pdc_topics(): Retrieves the list of topics (subcategories) that data is available for
pdc_datasets(): Retrieves identifiers, names, descriptions, and other metadata associated with the datasets in the (optionally specified) topics
pdc_read(): Imports a full dataset for the given identifier (datasetid). These are found in pdc_datasets().
pdc_read(datasetid, ...) pdc_datasets(topics = NULL) pdc_topics()pdc_read(datasetid, ...) pdc_datasets(topics = NULL) pdc_topics()
datasetid |
A dataset identifier (e.g., from |
... |
Additional arguments passed to |
topics |
A topic to list dataset metadata for (e.g., from |
A character vector listing available data topics, or a tibble::tibble() containing the requested data/metadata.
# 1. See list of available data topics pdc_topics() # 2. See list of datasets available for a topic hospital_data <- pdc_datasets("Hospitals") hospital_data # Find a dataset you want hospital_data |> dplyr::filter( stringr::str_detect( title, pattern = "(?i)readmission" ) ) # 3. Use that data set ID to import pdc_read("9n3s-kdb3")# 1. See list of available data topics pdc_topics() # 2. See list of datasets available for a topic hospital_data <- pdc_datasets("Hospitals") hospital_data # Find a dataset you want hospital_data |> dplyr::filter( stringr::str_detect( title, pattern = "(?i)readmission" ) ) # 3. Use that data set ID to import pdc_read("9n3s-kdb3")