Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating 2022 risk coefficients group mapping for HHS #53

Open
wants to merge 26 commits into
base: yp-version-update
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
1bd13a7
Merge pull request #42 from yubin-park/yp-version-update
yubin-park Oct 21, 2022
148f9a5
Fix file names.
rob-pomelo Jan 6, 2023
c43c37e
Drop duplicate version statement in README.md (#44)
proinsias Jan 21, 2023
8bb6584
FIX: typo of x["SEPSIS"] -> z["SEPSIS"] (#48)
daabbott-deloitte Jan 21, 2023
c7dfdb5
Merge pull request #45 from rob-pomelo/fix-file-names
yubin-park Feb 3, 2023
4e6b916
v28 added
yubin-park May 9, 2023
165ae6b
Merge pull request #57 from yubin-park/yubin_v28
yubin-park May 9, 2023
9bad5c2
fixed a few issues
yubin-park May 9, 2023
d5050a1
Merge pull request #59 from yubin-park/bugfix
yubin-park May 9, 2023
3fcec8c
agesex edits for V28
yubin-park May 11, 2023
8e23be7
Merge pull request #62 from yubin-park/yubin-ronnie-agesex-fix
yubin-park May 11, 2023
010ec8c
version number upgraded
yubin-park May 11, 2023
cc43613
Merge pull request #64 from yubin-park/yubin-ronnie-agesex-fix
yubin-park May 11, 2023
998530e
adding norm factors
yubin-park May 13, 2023
d3ad782
readme updated
yubin-park May 13, 2023
8b52cae
Merge pull request #65 from yubin-park/yubin-norm-factor
yubin-park May 13, 2023
11c5332
Update README.md
yubin-park Mar 31, 2024
ce94c32
Merge pull request #75 from yubin-park/yubin-park-patch-1
yubin-park Mar 31, 2024
68de457
Update README.md
yubin-park Mar 31, 2024
610203c
Updated v28 mapping to most recent available (2024 final).
dr00b Apr 10, 2024
e89bcc9
Bumped version
dr00b Apr 10, 2024
ad87398
Merge pull request #76 from yubin-park/v28-dx-mapping-update
yubin-park Apr 16, 2024
2ea532a
Update README.md
yubin-park Dec 14, 2024
d64525b
Merge pull request #79 from yubin-park/yubin-park-patch-2
yubin-park Dec 14, 2024
764d4ee
Update README.md
yubin-park Dec 14, 2024
b2e3c83
Merge pull request #80 from yubin-park/yubin-park-patch-3
yubin-park Dec 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
build/
dist/
*.egg-info
.vscode/

# Compiled source #
###################
Expand Down
77 changes: 73 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,40 @@
# NOTICE - Dec 13, 2024

# 📢 Repository Status Update

This repository has been succeeded by a new version!
We've created an enhanced version of this project with new features and improvements. You can find it here:
🔗 github.com/mimilabs/hccinfhir

# What This Means

This repository is no longer actively maintained
No new features or updates will be added here
For the latest features and support, please use the new repository

Thank you for your interest in this project! We encourage you to migrate to the new version to access the latest improvements.

---

# hccpy

Hierachical Condition Categories Python Package.

This module implements the [Hierachical Condition Categories](https://www.cms.gov/cciio/resources/forms-reports-and-other-resources/downloads/ra-march-31-white-paper-032416.pdf) that are used for adjusting risks for the Medicare population.
The original SAS implementation can be found [here](https://www.nber.org/data/cms-risk-adjustment.html).
Currently, hccpy supports CMS-HCC V22, V23, V24, ESRD, and HHS-HCC Year 2019.

NOTE: This package does not support for ICD-9.
NOTE: The latest version is 0.1.5 - updated on 10/20/2022.
NOTE: The latest version is 0.1.4 - updated on 09/13/2022.
The latest version is 0.1.10 which was released on 04/10/2024.

Currently, hccpy supports:
* CMS-HCC V22
* CMS-HCC V23
* CMS-HCC V24
* CMS-HCC V28
* CMS-HCC ESRD
* HHS-HCC 2019 (V05)
* HHS-HCC 2022 (V07)

Note that hccpy does not have support for ICD-9.

## Installing

Expand Down Expand Up @@ -131,6 +157,49 @@ To get a HCC profile from a list of diagnosis codes (in ICD-10):
>>>
```

### HCC for the new model, V28

Please use "V28" when initializing the engine.

```python
>>> from hccpy.hcc import HCCEngine
>>> he = HCCEngine("28")
```

Also, see the `test_v23()` examples in `tests/hcc_tests.py`.

### Coding Intensity Factor and Normalization Factors

You can add normalization factors and coding intensity factors to directly calculate the adjusted risk score.

By default, these two parameters are set as:

```python
cif = 0.059, # coding intensity factor.
norm_params={
"C": 1.015, # community/institution models
"D": 1.022, # ESRD Dialysis
"G": 1.028 # ESRD Graft
}
```

You can overwrite these parameters. For example, this setting below would not adjust the raw risk score.

```python
HCCEngine(version="28", cif = 0, norm_params={"C": 1})
```

To see the adjusted risk scores,
```python
>>> from hccpy.hcc import HCCEngine
>>> he = HCCEngine("28")
>>> rp = he.profile(["E1169", "I5030", "I509", "I211", "I209", "R05"],
age=70, sex="M", elig="CNA")
>>> rp["risk_score_adj"]
```

Also, see the `test_norm_factors()` examples in `tests/hcc_tests.py`.

### HCC-Profiling a New Member

If a member is new, then provide the `elig="NE"` in the input:
Expand Down
69 changes: 69 additions & 0 deletions hccpy/_E2118P1M.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from collections import Counter

def create_interactions(cc_lst, DISABL, age):

x = Counter(cc_lst)
z = Counter()

# payable HCC's count interaction
hcccnt = len([k for k in x.keys() if "HCC" in k])
if hcccnt > 9:
x["D10P"] = 1
elif hcccnt > 0:
x["D{}".format(hcccnt)] = 1

# diagnostic categories
z["CANCER"] = max(x["HCC8"], x["HCC9"], x["HCC10"],
x["HCC11"], x["HCC12"])
z["DIABETES"] = max(x["HCC17"], x["HCC18"], x["HCC19"])
z["IMMUNE"] = x["HCC47"]
z["CARD_RESP_FAIL"] = max(x["HCC82"], x["HCC83"], x["HCC84"])
z["CHF"] = x["HCC85"]
z["COPD"] = max(x["HCC110"], x["HCC111"])
z["RENAL"] = max(x["HCC134"], x["HCC135"], x["HCC136"],
x["HCC137"], x["HCC138"], x["HCC139"],
x["HCC140"], x["HCC141"])
z["COMPL"] = x["HCC176"]
z["SEPSIS"] = x["HCC2"]

# community model interactions
x["SEPSIS_CARD_RESP_FAIL"] = z["SEPSIS"] * z["CARD_RESP_FAIL"]
x["CANCER_IMMUNE"] = z["CANCER"] * z["IMMUNE"]
x["DIABETES_CHF"] = z["DIABETES"] * z["CHF"]
x["CHF_COPD"] = z["CHF"] * z["COPD"]
x["CHF_RENAL"] = z["CHF"] * z["RENAL"]
x["COPD_CARD_RESP_FAIL"] = z["COPD"] * z["CARD_RESP_FAIL"]

# institutional model interactions
x["NONAGED_HCC6"] = DISABL * x["HCC6"]
x["NONAGED_HCC34"] = DISABL * x["HCC34"]
x["NONAGED_HCC46"] = DISABL * x["HCC46"]
x["NONAGED_HCC54"] = DISABL * x["HCC54"]
x["NONAGED_HCC55"] = DISABL * x["HCC55"]
x["NONAGED_HCC110"] = DISABL * x["HCC110"]
x["NONAGED_HCC176"] = DISABL * x["HCC176"]

x["PRESSURE_ULCER"] = max(x["HCC157"], x["HCC158"],
x["HCC159"], x["HCC160"])
x["SEPSIS_PRESSURE_ULCER"] = z["SEPSIS"] * x["PRESSURE_ULCER"]
x["SEPSIS_ARTIF_OPENINGS"] = z["SEPSIS"] * x["HCC188"]
x["ART_OPENINGS_PRESSURE_ULCER"] = x["HCC188"] * x["PRESSURE_ULCER"]
x["DIABETES_CHF"] = z["DIABETES"] * z["CHF"]
x["COPD_ASP_SPEC_BACT_PNEUM"] = z["COPD"] * x["HCC114"]
x["ASP_SPEC_BACT_PNEUM_PRES_ULC"] = x["HCC114"] * x["PRESSURE_ULCER"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = z["SEPSIS"] * x["HCC114"]
x["SCHIZOPHRENIA_COPD"] = x["HCC57"] * z["COPD"]
x["SCHIZOPHRENIA_CHF"] = x["HCC57"] * z["CHF"]
x["SCHIZOPHRENIA_SEIZURES"] = x["HCC57"] * x["HCC79"]

x["NONAGED_HCC85"] = DISABL * x["HCC85"]
x["NONAGED_PRESSURE_ULCER"] = DISABL * x["PRESSURE_ULCER"]
x["NONAGED_HCC161"] = DISABL * x["HCC161"]
x["NONAGED_HCC39"] = DISABL * x["HCC39"]
x["NONAGED_HCC77"] = DISABL * x["HCC77"]

cc_lst = [k for k, v in x.items() if v > 0]

return cc_lst


6 changes: 6 additions & 0 deletions hccpy/_E2118P1P.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ def get_risk_dct(coefn, hcc_lst, age, sex):

# build hcc factor strings and add to risk_dict
for hcc in hcc_lst:
# NOTE: Other Eligibilities are not implemented
# DI: dialysis model
# DNE: dialysis new enrollees
# GC: graft community model
# GI: graft institutional model
# GNE: graft new enrollee
elig_hcc = "DI_" + hcc
risk_dct[elig_hcc] = coefn.get(elig_hcc, 0.0)

Expand Down
2 changes: 1 addition & 1 deletion hccpy/_V0519F3P.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def get_risk_dct(coefn, hcc_lst, agesexvar, agegroup, enroll_dur, plate):
for hcc in hcc_lst:
if agegroup+"_"+hcc in coefn:
risk_dct[hcc] = coefn[agegroup+"_"+hcc][plate]

return risk_dct


2 changes: 1 addition & 1 deletion hccpy/_V2218O1M.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def create_interactions(cc_lst, DISABL):
x["DIABETES_CHF"] = z["DIABETES"] * z["CHF"]
x["gCopdCF_ASP_SPEC_BACT_PNEUM"] = z["gCopdCF"] * x["HCC114"]
x["ASP_SPEC_BACT_PNEUM_PRES_ULC"] = x["HCC114"]*x["PRESSURE_ULCER"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = x["SEPSIS"] * x["HCC114"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = z["SEPSIS"] * x["HCC114"]
x["SCHIZOPHRENIA_gCopdCF"] = x["HCC57"] * z["gCopdCF"]
x["SCHIZOPHRENIA_CHF"] = x["HCC57"] * z["CHF"]
x["SCHIZOPHRENIA_SEIZURES"] = x["HCC57"] * x["HCC79"]
Expand Down
2 changes: 1 addition & 1 deletion hccpy/_V2318P1M.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def create_interactions(cc_lst, DISABL, age):
x["DIABETES_CHF"] = z["DIABETES"] * z["CHF"]
x["gCopdCF_ASP_SPEC_B_PNEUM"] = z["gCopdCF"] * x["HCC114"]
x["ASP_SPEC_BACT_PNEUM_PRES_ULC"] = x["HCC114"]*x["PRESSURE_ULCER"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = x["SEPSIS"] * x["HCC114"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = z["SEPSIS"] * x["HCC114"]
x["SCHIZOPHRENIA_gCopdCF"] = x["HCC57"] * z["gCopdCF"]
x["SCHIZOPHRENIA_CHF"] = x["HCC57"] * z["CHF"]
x["SCHIZOPHRENIA_SEIZURES"] = x["HCC57"] * x["HCC79"]
Expand Down
2 changes: 1 addition & 1 deletion hccpy/_V2419P1M.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def create_interactions(cc_lst, DISABL, age):
x["ART_OPENINGS_PRESSURE_ULCER"] = x["HCC188"]*x["PRESSURE_ULCER"]
x["gCopdCF_ASP_SPEC_B_PNEUM"] = z["gCopdCF"] * x["HCC114"]
x["ASP_SPEC_BACT_PNEUM_PRES_ULC"] = x["HCC114"]*x["PRESSURE_ULCER"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = x["SEPSIS"] * x["HCC114"]
x["SEPSIS_ASP_SPEC_BACT_PNEUM"] = z["SEPSIS"] * x["HCC114"]
x["SCHIZOPHRENIA_gCopdCF"] = x["HCC57"] * z["gCopdCF"]
x["SCHIZOPHRENIA_CHF"] = x["HCC57"] * z["CHF"]
x["SCHIZOPHRENIA_SEIZURES"] = x["HCC57"] * x["HCC79"]
Expand Down
57 changes: 57 additions & 0 deletions hccpy/_V2823T2M.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from collections import Counter

def create_interactions(cc_lst, DISABL, age):

x = Counter(cc_lst)
z = Counter()

# payable HCC's count interaction
hcccnt = len([k for k in x.keys() if "HCC" in k])
if hcccnt > 9:
x["D10P"] = 1
elif hcccnt > 0:
x["D{}".format(hcccnt)] = 1

# diagnostic categories
z["CANCER"] = max(x["HCC17"], x["HCC18"], x["HCC19"],
x["HCC20"], x["HCC21"], x["HCC22"], x["HCC23"])
z["DIABETES"] = max(x["HCC35"], x["HCC36"], x["HCC37"], x["HCC38"])
z["CARD_RESP_FAIL"] = max(x["HCC211"], x["HCC212"], x["HCC213"])
z["HF"] = max(x["HCC221"], x["HCC222"], x["HCC223"],
x["HCC224"], x["HCC225"], x["HCC226"])
z["CHR_LUNG"] = max(x["HCC276"], x["HCC277"], x["HCC278"],
x["HCC279"], x["HCC280"])
z["KIDNEY"] = max(x["HCC326"], x["HCC327"], x["HCC328"], x["HCC329"])
z["SEPSIS"] = x["HCC2"]
z["gSubUseDisorder"] = max(x["HCC135"], x["HCC136"], x["HCC137"],
x["HCC138"], x["HCC139"])
z["gPsychiatric"] = max(x["HCC151"], x["HCC152"],
x["HCC153"], x["HCC154"], x["HCC155"])
z["NEURO"] = max(x["HCC180"], x["HCC181"], x["HCC182"],
x["HCC190"], x["HCC191"], x["HCC192"],
x["HCC195"], x["HCC196"], x["HCC198"],
x["HCC199"])
z["ULCER"] = max(x["HCC379"], x["HCC380"], x["HCC381"], x["HCC382"])

# community model interactions
# NOTE: updated interaction codes to match V24hcccoefn.csv; values changed from V23 --> V24
x["DIABETES_HF"] = z["DIABETES"] * z["HF"]
x["HF_CHR_LUNG"] = z["HF"] * z["CHR_LUNG"]
x["HF_KIDNEY"] = z["HF"] * z["KIDNEY"]
x["CHR_LUNG_CARD_RESP_FAIL"] = z["CHR_LUNG"] * z["CARD_RESP_FAIL"]
x["HF_HCC238"] = z["HF"] * x["HCC238"]
x["gSubUseDisorder_gPsych"] = (z["gSubUseDisorder"] *
z["gPsychiatric"])

# institutional model interactions
x["DISABLED_CANCER"] = DISABL * z["CANCER"]
x["DISABLED_NEURO"] = DISABL * z["NEURO"]
x["DISABLED_HF"] = DISABL * z["HF"]
x["DISABLED_CHR_LUNG"] = DISABL * z["CHR_LUNG"]
x["DISABLED_ULCER"] = DISABL * z["ULCER"]

cc_lst = [k for k, v in x.items() if v > 0]

return cc_lst


64 changes: 64 additions & 0 deletions hccpy/_V28I0ED1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@

# contribution by @ronnie-canopy

def apply_agesex_edits(cc_dct, age, sex):
# age/sex edits. see "V28I0ED1.TXT"

# Factor VIII or XI deficiency
e_set0 = {"D66", "D67"}

e_set1 = {
"J410", "J411", "J418", "J42", "J430",
"J431", "J432", "J438", "J439", "J440",
"J441", "J449", "J982", "J983"
}

e_set2 = {
"C50011", "C50012", "C50019", "C50021",
"C50022", "C50029", "C50111", "C50112",
"C50119", "C50121", "C50122", "C50129",
"C50211", "C50212", "C50219", "C50221",
"C50222", "C50229", "C50311", "C50312",
"C50319", "C50321", "C50322", "C50329",
"C50411", "C50412", "C50419", "C50421",
"C50422", "C50429", "C50511", "C50512",
"C50519", "C50521", "C50522", "C50529",
"C50611", "C50612", "C50619", "C50621",
"C50622", "C50629", "C50811", "C50812",
"C50819", "C50821", "C50822", "C50829",
"C50911", "C50912", "C50919", "C50921",
"C50922", "C50929"
}

e_set3 = {
"P040", "P041", "P0411", "P0412",
"P0413", "P0414", "P0415", "P0416",
"P0417", "P0418", "P0419", "P041A",
"P042", "P043", "P0440", "P0441",
"P0442", "P0449", "P045", "P046",
"P048", "P0481", "P0489", "P049",
"P270", "P271", "P278", "P279",
"P930", "P938", "P961", "P962"
}

if sex == "F":
# for dx in (dx for dx in elst0 if dx in cc_dct):
for dx in (e_set0 & cc_dct.keys()):
cc_dct[dx] = ["HCC112"] # Immune Thrombocytopenia and Specified Coagulation Defects and Other Specified Hematological Disorders

if age < 18:
# for dx in (dx for dx in elst1 if dx in cc_dct):
for dx in (e_set1 & cc_dct.keys()):
cc_dct[dx] = ["HCCNA"] # Respiritry codes

if age < 50 :
# for dx in (dx for dx in elst2 if dx in cc_dct):
for dx in (e_set2 & cc_dct.keys()):
cc_dct[dx] = ["HCC22"] # Bladder, Colorectal, and Other Cancers

if age >= 2 :
# for dx in (dx for dx in elst3 if dx in cc_dct):
for dx in (e_set3 & cc_dct.keys()):
cc_dct[dx] = ["HCCNA"] # Newborn codes

return cc_dct
Loading