Python code to convert CMS-HCC crosswalks and Stata hierarchy code found at CMS.gov into nicely formatted tables usable in R or Python.
The CMS-HCC generation is done in Python and requires pandas 0.21.0 or greater (otherwise pandas.DataFrame.drop()
will throw an error).
A more throrough walkthrough of the code can be found in the Worked Example.
All of the ICD to CC crosswalks have been cleaned for all years between 2009 and 2017 for both ICD9 and ICD10 and all versions of the CMS-HCCs. The raw crosswalks can be found under Raw/
and the resulting formatted crosswalks are in Crosswalks/
. The formatted tables include column headings and columns indicating the year the mapping is valid for and the ICD version.
cc icd version year
0 2 0031 9 2009
1 112 00322 9 2009
2 37 00323 9 2009
3 37 00324 9 2009
4 112 0064 9 2009
The Hierarchical Condition Categories and hierarchy rules were also extracted from the raw Stata files found in Raw/
and were placed in formatted tables under ConditionCategory/
. For each CMS-HCC version, the labels file lists all HCC codes and the descriptive label:
cc label
0 1 HIV/AIDS ...
1 2 Septicemia/Shock ...
2 5 Opportunistic Infections ...
3 7 Metastatic Cancer and Acute Leukemia ...
4 8 Lung, Upper Digestive Tract, and Other Severe ...
The rules files list the hierarchical rules. This file can be interpreted as: if the Category Code in cc
is assigned to a person, then zero the Category code in to_zero
.
to_zero cc
0 112 5
1 8 7
2 9 7
3 10 7
4 9 8
The HCCs for each person are then generated based on the crosswalks and the years with RiskAdjustment.py. The input table must be a long diagnosis table where each row list a single diagnosis for an individual and also includes the date and icd version.
recip_id icd date version
0 4224 Z7689 2016-01-01 10
1 4473 Z7689 2016-01-01 10
2 3348 G8929 2016-01-01 10
3 3956 Z7689 2016-01-01 10
4 1640 I776 2016-01-01 10
recip_id int64
icd object
date datetime64[ns]
version int64
The date should be a datetime object which can be accomplished with pandas.to_datetime()
before passing the DataFrame
to generate_hccs()
. For this to work as is, the columns should be named exactly as above, otherwise edit the merges in RiskAdjustment.py accordingly for your variable names.
The HCC table is then generated by supplying the input DataFrame
and specifying which version of the CMS-HCCs to use.
import RiskAdjustment as ra
ra.generate_hccs(sample_data, 'v21')
cc 1 2 6 8 18 ...
recip_id
3 False False False False False ...
5 False False False False False ...
6 False False False False False ...
7 False False False False False ...
8 False False False False False ...
9 False False False False False ...
10 False False False False False ...
11 False False False False False ...
12 False False False False True ...
13 False False False False False ...
The output is a table with one row for each unique person in the input DataFrame
who has at least one HCC assigned to them.