Machine-Readable File (MRF) Comparison Tool

MRF Comparison Tool was made for performing informal desk audits of the MRFs that insurers and hospitals were required to make publicly available from the two rules CMS made. I was tasked with looking at the prices for charge items/services in the MRFs to find out if price per item matched between the insurers and hospitals files.

This work supported CMS in their price transparency initivaitves for both health insurers and hospitals.

Usage

  ./mrf-comparison.py

Running the tool from the command line compares the two MRFS and produces an Excel workbook and finds matching charge items between them. This allows us to compare the reported price in one file versus the other.

Technical Explanation

Taking the usual form of a python script it starts with a python shebang and importing dependencies, followed by a main function that will be called as the last step in the script.

We will stay in main() until the script calls the main function last:

#!/usr/local/bin/python3

import csv
import openpyxl
import json
from datetime import datetime
import numpy as np
import pandas as pd

def main():

Next we use pandas to create DataFrames of both MRFs from insurers and hospitals:

    # Hospital MRF dataframe
    hpt_df = pd.read_excel(
    "https://healthcare.ascension.org/-/media/project/ascension/healthcare/price-transparency-files/in/350869066_ascension-st-vincent-hospital_standardcharges.xlsx",
    'Standard Charges', header=1, usecols='B, C, D, E, F, G, H, I, J, AF,AG, AH, AI, BR')

    # Insurer MRF dataframe
    tic_df = pd.read_json(
        "https://mysmarthealth.org/-/media/Files/SmartHealth/Documents/Transparency-in-coverage/2022-06-24_ABS_AscensionSmartHealth_in-network-rates.json?la=en&hash=71F0E7907ADFED24203A25BCB20FD8EF380CF477",
        orient='columns')

After initializing a variable to help us collect the hospital-specific charge items, we begin to iterate through the insurer MRF file, creating a frame for each in_network object we encounter:

    asc_items = []

    for row in tic_df.itertuples():
        # create frame for in_network object
        df = pd.DataFrame.from_dict(row.in_network)

These objects represent the in-network rates files outlined in the rule. A ‘rate’ here means the price of a charge item under this plan.

For every in-network rate we encounter we want to iterate through its negotiated rates with providers and gather:

        for rate in df.itertuples():
            negotiated_rate_details_object = rate.negotiated_rates
            # The negotiated price
            negotiated_prices_object = pd.DataFrame.from_dict(negotiated_rate_details_object['negotiated_prices'])
            
            providers = pd.DataFrame.from_dict(negotiated_rate_details_object['provider_groups'])
            # The providers' tax identification numbers
            tin = pd.DataFrame.from_records(providers['tin'])

This next part uses the Tax Identification Number (hardcoded) for the hospital we pulled the MRF of in the first step. This can be changed to the TIN of whichever hospital you pulled the MRF of. You do not need to change anything for the insurer file, you need only supply it.

We look through the TINs of the providers to find the TIN of the hospital we are interested in. If found, we create an item for the charge item and append it to the list variable:

            # the hardcoded hospital tin
            if tin.value.loc[0] == '350869066' and tin.type.loc[0] == 'ein':
                # create item
                asc_item_name = df.name.loc[0]
                asc_item_billing_code = df.billing_code.loc[0]
                asc_item_code_type = df.billing_code_type.loc[0]
                asc_item_negotiated_price = negotiated_prices_object.negotiated_rate.loc[0]
                # append item
                asc_items.append([asc_item_billing_code, asc_item_code_type, asc_item_name, asc_item_negotiated_price])

Now that we have the hospitals in-network charge items from the insurer MRF in asc_items, we create a new dataframe with those items and begin to process the hospital MRF.

    tic_comparison_df = pd.DataFrame.from_records(data=asc_items, columns=['Code', 'Code_Type', 'Description', '"TiC-Parsed" Negotiated Price'])
    # only include columns from the hospital file we are interested in
    hpt_comparison_df = hpt_df[
        ["Code", "Code_Type", "Description", "Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3499",
         "Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_2364", "Commercial_Other_SMARTHEALTH_SMARTHEALTH_3499",
         "Commercial_Other_SMARTHEALTH_SMARTHEALTH_2364",
         "Blue_Cross_Blue_Shield_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3943"]]

Now we merge the two frames on the billing code for the charge item to bridge the two data sets. This is where the charge items from both data sets are connected. We need to select the columns on the resulting merge dataframe that we need, and then rename them.

    result_merge = hpt_comparison_df.merge(tic_comparison_df, how='inner', on='Code')
    # column select
    result_merge = result_merge[['Code', 'Code_Type_x', 'Code_Type_y', '"TiC-Parsed" Negotiated Price',
                     'Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3499',
                     'Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_2364',
                     'Commercial_Other_SMARTHEALTH_SMARTHEALTH_3499',
                     'Commercial_Other_SMARTHEALTH_SMARTHEALTH_2364',
                     'Blue_Cross_Blue_Shield_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3943', 'Description_x',
                     'Description_y']]
    rename_dict = {'Code': 'Code', 'Code_Type_x': 'Code_Type_HPT', 'Code_Type_y': 'Code_Type_TiC',
                   '"TiC-Parsed" Negotiated Price': 'TiC-Parsed Negotiated Price',
                   'Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3499': 'SMARTHEALTH_PPO_HDHP_ASCEN_3499',
                   'Commercial_Other_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_2364': 'SMARTHEALTH_PPO_HDHP_ASCEN_2364',
                   'Commercial_Other_SMARTHEALTH_SMARTHEALTH_3499': 'SMARTHEALTH_SMARTHEALTH_3499',
                   'Commercial_Other_SMARTHEALTH_SMARTHEALTH_2364': 'SMARTHEALTH_SMARTHEALTH_2364',
                   'Blue_Cross_Blue_Shield_SMARTHPPOA_SMARTHEALTH_PPO_HDHP_ASCEN_3943': 'BCBS - SMARTHEALTH_PPO_HDHP_ASCEN_3943',
                   'Description_x': 'HPT Description',
                   'Description_y': 'TiC Description'}
    # column rename
    result_merge = result_merge.rename(rename_dict, axis="columns")

Lastly we need to export the merged information to an Excel workbook. We are including the base insurer and hospital frames as well:

    with pd.ExcelWriter("HPT_Billing_Information.xlsx") as writer:
        hpt_df.to_excel(writer, sheet_name='HPT Billing Code Items', na_rep='N/A', float_format='%.2f')
        tic_df.to_excel(writer, 'TiC Billing Code Items', na_rep='N/A')
        result_merge.to_excel(writer, 'inner join on Code value', na_rep='N/A', float_format='%.2f')
        

That concludes main(). Now all that’s left to do is to call it.

if __name__ == '__main__':
    main()