# Comorbidity measures

To calculate the comorbidities in my upcoming article in the Bone and Joint Journal I have used the python plugin for IBM SPSS. The code is both validated manually on a subset of patients and tested by the codes defined in Dr. Hude Quan’s code.

In order to speed up the code I have a simple ICD-10 detector, if you’re not working in Sweden then leave the year parameter set to False:

```def IsIcd10Code(icd, year = False):
# If year was specified then Sweden changed to ICD 10
# in 1997 but since not everyone change at the same time
# 1996 to 1999 are considered safer to perform a
# regex format check as belov
if (year):
if (year < 1996):
return False
elif(year > 1999):
return True

# No true ICD 10 codes have a V in them except for transportation
# accidents and those don't count although ICD 9 has a few odd V
# codes in it.
if (re.match("[A-Z][0-9]+", icd, re.IGNORECASE)
and re.match("[^V][0-9]+", icd, re.IGNORECASE)):
return True
else:
return False
```

Now the code to identify a Charlson ICD-code is below. There are two versions of the Charlson codes, one is the Sundarajan et al’s 2004 version and the second one is Quan et al’s 2005 version:

```def FindCharlsonsMatch(icdCode, icd_ver = False, version = 2, print_debug = False):
"""Checks if the icd code exists in any of the expressions and
returns a string with the code for the charlsons"""

# Create the charlsons regular expressions
# to compare 2
# v1 is based on Sundarajan et al 2004
charlsons_v1 = {}
charlsons_v1['MI'] = {'icd9': ['41[02]'],
'icd10': ['I2([12]|52)']}

charlsons_v1['CHF'] = {'icd9': ['428'],
'icd10': ['I50']}

charlsons_v1['PVD'] = {'icd9': ['44(1|39)', '7854', 'V434'],
'icd10': ['I7(1|90|39)', 'R02', 'Z95[89]']}

charlsons_v1['CEVD'] = {'icd9': ['43[012345678]'],
'icd10': ['I6([01234569]|7[012456789]|8[128])', 'G45[0124689]', 'G46']}

charlsons_v1['DEM'] = {'icd9': ['290'], 'icd10': ['F0([012]|51)']}

charlsons_v1['COPD'] = {'icd9': ['49[0123456]', '50[012345]'],
'icd10': ['J4[01234567]', 'J6[01234567]']}

charlsons_v1['Rheum'] = {'icd9': ['710[014]', '714[012]', '71481', '5171', '725'],
'icd10': ['M3([24]|32|53)', 'M0(5[012389]|6[039])']}

charlsons_v1['PUD'] = {'icd9': ['53[1234]'],
'icd10': ['K2[5678]']}

charlsons_v1['MILDLD'] = {'icd9': ['571[2456]'],
'icd10': ['K7(0[23]|17|3|4[023456])']}

charlsons_v1['DIAB_UC'] = {'icd9': ['250[01237]'],
'icd10': ['E1[0134][159]']}

charlsons_v1['DIAB_C'] = {'icd9': ['250[456]'],
'icd10': ['E1[0134][234]']}

charlsons_v1['PARA'] = {'icd9': ['342', '3441'],
'icd10': ['G041', 'G8(1|2[012])']}

charlsons_v1['RD'] = {'icd9': ['58([2568]|3[01234567])'],
'icd10': ['N0([13]|5[23456]|7[234])', 'N1[89]', 'N25']}

charlsons_v1['CANCER'] = {'icd9': ['1([4568]|7[0124569]|9[0123459])', '20[012345678]'],
'icd10': ['C[012356]', 'C4[01356789]', 'C7[0123456]', 'C8([12345]|8[379])', 'C9(0[01]|[12356]|4([01237]|51))']}

charlsons_v1['METS'] = {'icd9': ['19([678]|9[01])'],
'icd10': ['C7[789]', 'C80']}

charlsons_v1['MSLD'] = {'icd9': ['572[2348]'],
'icd10': ['K7(04|2[19]|6[67])']}

charlsons_v1['HIV'] = {'icd9': ['04[234]'],
'icd10': ['B2[01234]']}

# Based on Quan et al 2005
charlsons_v2 = {}
charlsons_v2['MI'] = {'icd10': ['I2([12]|52)'],
'icd9': ['41[02]']}

charlsons_v2['CHF'] = {'icd10': ['I099', 'I1(10|3[02])', 'I255', 'I4(2[056789]|3)', 'I50', 'P290'],
'icd9': ['39891', '402(01|11|91)', '404(01|03|[19][13])', '42(5[456789]|8)']}

charlsons_v2['PVD'] = {'icd10': ['I7([01]|3[189]|71|9[02])', 'K55[189]', 'Z95[89]'],
'icd9': ['0930', '4373', '44([01]|3[123456789]|71)', '557[19]', 'V434']}

charlsons_v2['CEVD'] = {'icd10': ['G4[56]', 'H340', 'I6'],
'icd9': ['36234', '43[012345678]']}

charlsons_v2['DEM'] = {'icd10': ['F0([0123]|51)', 'G3(0|11)'],
'icd9': ['29(0|41)', '3312']}

charlsons_v2['COPD'] = {'icd10': ['I27[89]', 'J4[01234567]', 'J6([01234567]|84)', 'J70[13]'],
'icd9': ['416[89]', '49', '50([012345]|64|8[18])']}

charlsons_v2['Rheum'] = {'icd10': ['M0[56]', 'M3(15|[234]|5[13]|60)'],
'icd9': ['4465', '71(0[01234]|4[0128])', '725']}

charlsons_v2['PUD'] = {'icd10': ['K2[5678]'],
'icd9': ['53[1234]']}

charlsons_v2['MILDLD'] = {'icd10': ['B18', 'K7(0[01239]|1[3457]|[34]|6[023489])', 'Z944'],
'icd9': ['070([23][23]|[45]4|[69])', '57([01]|3[3489])', 'V427']}

charlsons_v2['DIAB_UC'] = {'icd10': ['E1[01234][01689]'],
'icd9': ['250[012389]']}

charlsons_v2['DIAB_C'] = {'icd10': ['E1[01234][23457]'],
'icd9': ['250[4567]']}

charlsons_v2['PARA'] = {'icd10': ['G041', 'G114', 'G8(0[12]|[12]|3[012349])'],
'icd9': ['3341', '34([23]|4[01234569])']}

charlsons_v2['RD'] = {'icd10': ['I120', 'I131', 'N0(3[234567]|5[234567])', 'N1[89]', 'N250', 'Z49[012]', 'Z940', 'Z992'],
'icd9': ['403[019]1', '404[019][23]', '58(2|3[01234567]|[56]|80)', 'V4(20|51)', 'V56']}

charlsons_v2['CANCER'] = {'icd10': ['C[01]', 'C2[0123456]', 'C3[01234789]', 'C4[01356789]', 'C5[012345678]', 'C6', 'C7[0123456]', 'C8[123458]', 'C9[01234567]'],
'icd9': ['1[456]', '17[012456789]', '18', '19[012345]', '20[012345678]', '2386']}

charlsons_v2['MSLD'] = {'icd10': ['I8(5[09]|64)', 'I982', 'K7(04|[12]1|29|6[567])'],
'icd9': ['456[012]', '572[2345678]']}

charlsons_v2['METS'] = {'icd10': ['C7[789]', 'C80'],
'icd9': [ '19[6789]']}

charlsons_v2['HIV'] = {'icd10': ['B2[0124]'],
'icd9': [ '04[234]']}

charlson_4_comparing = charlsons_v2
if (version == 1):
charlson_4_comparing = charlsons_v1

# Speeds up only to check the codes that are possible
if (icd_ver == False):
code_is_icd10 = IsIcd10Code(icdCode)
else:
code_is_icd10 = icd_ver == 10

matches = {}
for key_disease, reg_expr in charlson_4_comparing.iteritems():
if (code_is_icd10 == False and matches.has_key(key_disease) == False):
for expr in reg_expr['icd9']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-9 match based on this Charlsons expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break
if (code_is_icd10 == True and matches.has_key(key_disease) == False):
for expr in reg_expr['icd10']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-10 match based on this Charlsons expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break

return matches
```

The Royal Collegue of Surgeon’s Charlson score uses the script below:

```def FindRoyalCharlsonsMatch(icdCode, prev_hosp_admission, icd_ver = False, only_icd10 = True, print_debug = False):
"""Checks if the icd code exists in any of the expressions and
returns a string with the code for the charlsons

Certain codes are only valid if previous hospital admission and therefore this needs
to have the prev_hosp_admission variable set to True/False depending if the icd code
is generated from a previous hospital visit or not.
"""

# Based on Armitage JN, van der Meulen JH.
# -- Identifying co-morbidity in surgical patients using
# --- administrative data with the Royal College of Surgeons Charlson Score.
# -- British Journal of Surgery. 2010 Maj 1;97(5):772-781.

rs_charlsons = {}
rs_charlsons['MI'] = {'icd10': ['I2([123]|52)'],
'icd9': ['41[02]']}

rs_charlsons['CHF'] = {'icd10': ['I1[13]', 'I255', 'I4[23]', 'I50', 'I517'],
'icd9': ['39891', '402(01|11|91)', '404(01|03|[19][13])', '42(5[456789]|8)']}

rs_charlsons['PVD'] = {'icd10': ['I7[0123]', 'I77[01]', 'K55[189]', 'R02', 'Z95[89]'],
'icd9': ['0930', '4373', '44([01]|3[123456789]|71)', '557[19]', 'V434']}

rs_charlsons['CEVD'] = {'icd10': ['G4[56]', 'I6'],
'icd9': ['36234', '43[012345678]']}

rs_charlsons['DEM'] = {'icd10': ['A810','F0([0123]|51)', 'G3[01]'],
'icd9': ['29(0|41)', '3312']}

rs_charlsons['COPD'] = {'icd10': ['I26', 'I27', 'J4[01234567]', 'J6([01234567]|84)', 'J70[13]'],
'icd9': ['416[89]', '49', '50([012345]|64|8[18])']}

rs_charlsons['Rheum'] = {'icd10': ['M0[569]', 'M120', 'M3(15|[23456])'],
'icd9': ['4465', '71(0[01234]|4[0128])', '725']}

rs_charlsons['LD'] = {'icd10': ['B18', 'I85', 'I864', 'I982', 'K7([01]|2[19]|6)', 'R162', 'Z944'],
'icd9': ['070([23][23]|[45]4|[69])', '456[012]', '572[2345678]', '57([01]|3[3489])', 'V427']}

rs_charlsons['DIAB'] = {'icd10': ['E1[01234]'],
'icd9': ['250']}

rs_charlsons['PARA'] = {'icd10': ['G114', 'G8[123]'],
'icd9': ['3341', '34([23]|4[01234569])']}

rs_charlsons['RD'] = {'icd10': ['I1[23]', 'N0[13578]', 'N1(7[12]|[89])', 'N25', 'Z49', 'Z940', 'Z992'],
'icd9': ['403[019]1', '404[019][23]', '58(2|3[01234567]|[56]|80)', 'V4(20|51)', 'V56']}

rs_charlsons['CANCER'] = {'icd10': ['C[01]', 'C2[0123456]', 'C3[01234789]', 'C4[01356789]', 'C5[012345678]', 'C6', 'C7[0123456]', 'C8[0123458]', 'C9[01234567]'],
'icd9': ['1[456]', '17[012456789]', '18', '19[012345]', '20[012345678]', '2386']}

rs_charlsons['METS'] = {'icd10': ['C7[789]'],
'icd9': [ '19[6789]']}

rs_charlsons['HIV'] = {'icd10': ['B2[0124]'],
'icd9': [ '04[234]']}

regexp_4_idc10_acute_diagnos_codes = '(I2[123]|J46|N17[12]|N19)'

# Used the translator from Socialstyrelsen
regexp_4_idc9_acute_diagnos_codes = '(410|42(30|95|96|98)|4939|58[34][67]|5908|586|7919|5939)'

# Speeds up only to check the codes that are possible
if (icd_ver == False):
code_is_icd10 = IsIcd10Code(icdCode)
else:
code_is_icd10 = icd_ver == 10

matches = {}
for key_disease, reg_expr in rs_charlsons.iteritems():
# ICD 9 part
if (code_is_icd10 == False and only_icd10 == False and matches.has_key(key_disease) == False):
# Check that none of the acute diagnoses is checked
if (prev_hosp_admission == True or re.match(regexp_4_idc9_acute_diagnos_codes, icdCode, re.IGNORECASE) == None):
for expr in reg_expr['icd9']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-9 match based on this org. Charlsons expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break

# ICD 10 part
if (code_is_icd10 == True and matches.has_key(key_disease) == False):
# Check that none of the acute diagnoses is set
re.match(regexp_4_idc10_acute_diagnos_codes, icdCode, re.IGNORECASE) == None):
for expr in reg_expr['icd10']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-10 match based on this RS Charlsons expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break

return matches
```

While the Elixhauser score has the below function:

```def FindElixhausersMatch(icdCode, icd_ver = False, print_debug=False):
"""Checks if the icd code exists in any of the expressions and
returns a string with the code for the elixhausers"""

elixhausers = {}
#Congestive heart failure
elixhausers['CHF'] = {'icd-10': ['I099', 'I1(10|3[02])', 'I255', 'I4(2[056789]|3)', 'I50', 'P290'],
#'icd-9': ['39891', '402(01|11|91)', '404(01|03|[19][13])', '42(5[456789]|8)']}
# Changes due to the Swedish coding
'icd-9': ['3980', '402', '4040', '42(5[456789]|8)']}

# Cardiac arrhythmias
elixhausers['Arrhy'] = {'icd-10': ['I44[123]', 'I456', 'I459',
'I4[789]', 'R00[018]', 'T821',
'Z[49]50'],
#'icd-9':['426([079]|1[023])',
#Swedish changes
'icd-9':['426[079]',
'427[01234]',
'427[6789]', '7850',
#'9960[14]',
'V450', 'V533']}

# Valvular disease
elixhausers['VD'] = {'icd-10': ['A520', 'I0[5678]',
'I09[18]', 'I3[456789]',
'Q23[0123]', 'Z95[234]'],
'icd-9':['0932', '39[4567]', '424',
'746[3456]', 'V422', 'V433']}

# Pulmonary circulation disorders
elixhausers['PCD'] = {'icd-10': ['I2([67]|8[089])'],
'icd-9':['415[01]', '416',
'417[089]']}

elixhausers['PVD'] = {'icd-10': ['I7([01]|3[189]|71|9[02])', 'K55[189]', 'Z95[89]'],
'icd-9': ['0930', '4373', '44([01]|3[123456789])', '4471', '557[19]', 'V434']}

# Hypertension, uncomplicated
elixhausers['HPTN_UC'] = {'icd-10': ['I10'],
'icd-9':['401']}

# Hypertension, complicated
elixhausers['HPTN_C'] = {'icd-10': ['I1[1235]'],
'icd-9':['40[2345]']}

# Paralysis
elixhausers['Para'] = {'icd-10': ['G041', 'G114', 'G8(0[12]|[12]|3[012349])'],
'icd-9': ['3341', '34([23]|4[01234569])']}

# Other neurological disorders
elixhausers['OthND'] = {'icd-10':['G1[0123]', 'G2[012]', 'G25[45]',
'G31[289]',
'G3[2567]',
'G4[01]', 'G93[14]',
'R470', 'R56'],
'icd-9': ['3319', '332[01]',
'333[45]',
'33([45]|62)',
'34([015]|8[13])',
'78[04]3']}

# Chronic pulmonary disease
elixhausers['COPD'] = {'icd-10': ['I27[89]', 'J4[01234567]', 'J6([01234567]|84)', 'J70[13]'],
'icd-9': ['416[89]', '49', '50([012345]|64|8[18])']}

# Diabetes, uncomplicated
# Slightly different from charlsons
elixhausers['Diab_UC'] = {'icd-10': ['E1[01234][019]'],
'icd-9': ['250[0123]']}

# Diabetes, complicated
# Slightly different from charlsons
elixhausers['Diab_C'] = {'icd-10': ['E1[01234][2345678]'],
'icd-9': ['250[456789]']}

# Hypothyroidism
elixhausers['Hptothy'] = {'icd-10': ['E0[0123]', 'E890'],
'icd-9':['2409', '24([34]|6[18])']}

# Renal failure
# Differs from Charlsons
elixhausers['RF'] = {'icd-10': ['I120', 'I131', 'N1[89]', 'N250', 'Z49[012]', 'Z940', 'Z992'],
#'icd-9': ['403[019]1', '404[019][23]', '58([56]|80)', 'V4(20|51)', 'V56']}
# Swe change
'icd-9': ['403', '404', '58([56]|80)', 'V4(20|51)', 'V56']}

# Liver disease
elixhausers['LD'] = {'icd-10': ['B18', 'I8(5|64)', 'I982', 'K7(0|1[13457]|[234]|6[023456789])', 'Z944'],
#'icd-9': ['070([23][23]|[45]4|[69])', '456[012]', '57([01]|2[2345678]|3[3489])', 'V427']}
# Swe changes
'icd-9': ['070([23]|[45])', '456[012]', '57([01]|2[2345678]|3[3489])', 'V427']}

# Peptic ulcer disease excluding bleeding
elixhausers['PUD_NB']  = {'icd-10': ['K2[5678][79]'],
'icd-9': ['53[1234][79]']}

# AIDS/HIV
elixhausers['HIV'] = {'icd-10': ['B2[0124]'],
'icd-9': ['04[234]']}

# Lymphoma
elixhausers['Lymp'] = {'icd-10': ['C8[123458]',
'C96', 'C90[02]'],
'icd-9':['20[012]', '2030', '2386']}

# Metastatic cancer
elixhausers['METS'] = {'icd-10': ['C7[789]', 'C80'],
'icd-9': ['19[6789]']}

# Solid tumor without metastasis
elixhausers['Tumor'] = {'icd-10': ['C[01]', 'C2[0123456]',
'C3[01234789]', 'C4[01356789]', 'C5[012345678]',
'C6', 'C7[0123456]', 'C97'],
'icd-9': ['1[456]', '17[012456789]', '18', '19([012345])']}

# Rheumatoid arthritis/collagen vascular diseases
elixhausers['Rheum_A'] = {'icd-10': ['L94[013]', 'M0[568]', 'M12[03]',
'M3(0|1[0123]|[2345])', 'M4(5|6[189])'],
#'icd-9': ['446', '7010', '71(0[0123489]|12|4|93)', '72([05]|8(5|89)|930)']}
'icd-9': ['446', '7010', '71(0[0123489]|12|4|93)', '72([05]|8[58]|93)']}

# Coagulopathy
elixhausers['Coag'] = {'icd-10': ['D6[5678]',
'D69[13456]'],
'icd-9':['286', '2871', '287[345]']}

# Obesity
elixhausers['Obesity'] = {'icd-10': ['E66'],
'icd-9':['2780']}

# Weight loss
elixhausers['WL'] = {'icd-10': ['E4[0123456]', 'R634', 'R64'],
'icd-9':['26[0123]', '7832', '7994']}

# Fluid and electrolyte disorders
elixhausers['Fluid'] = {'icd-10': ['E222', 'E8[67]'],
'icd-9':['2536', '276']}

# Blood loss anemia
elixhausers['BLA'] = {'icd-10': ['D500'],
'icd-9':['2800']}

# Deficiency anemia
elixhausers['DA'] = {'icd-10': ['D50[89]', 'D5[123]'],
'icd-9':['280[123456789]', '281']}

# Alcohol abuse
elixhausers['Alcohol'] = {'icd-10': ['F10', 'E52', 'G621', 'I426',
'K292', 'K70[039]',
'T51', 'Z502',
'Z714', 'Z721'],
'icd-9':['2652', '291[12356789]',
'303[09]', '3050', '3575',
'4255', '5353', '571[0123]', '980', 'V113']}

# Drug abuse
elixhausers['Drug'] = {'icd-10': ['F1[12345689]',
'Z715', 'Z722'],
'icd-9':['292', '304', '305[23456789]', 'V6542']}

# Psychoses
elixhausers['Psycho'] = {'icd-10': ['F2[0234589]',
'F3([01]2|15)'],
'icd-9':['2938',
#'296[0145]4',
# Changes in Swedish version
'296[08]',
'29[578]']}

# Depression
elixhausers['Dep'] = {'icd-10': ['F204',
'F31[345]', 'F3[23]',
'F341', 'F4[13]2'],
'icd-9':[
#'296[235]',
# Changes in Swedish version
'296[135]',
'3004', '309', '311']}

# Speeds up only to check the codes that are possible
if (icd_ver == False):
code_is_icd10 = IsIcd10Code(icdCode)
else:
code_is_icd10 = icd_ver == 10

matches = {}
for key_disease, reg_expr in elixhausers.iteritems():
try:
if (code_is_icd10 == False and matches.has_key(key_disease) == False):
for expr in reg_expr['icd-9']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-9 match based on this Elixhausers expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break
if (code_is_icd10 == True and matches.has_key(key_disease) == False):
for expr in reg_expr['icd-10']:
if (re.match(expr, icdCode, re.IGNORECASE)):
if (print_debug):
print "The code {0} has an icd-10 match based on this Elixhausers expression = '{1}'".format(icdCode, expr)
matches[key_disease] = 1
break
except Exception, e:
print "\n******"
print "Exception for regexp {0}".format(expr)
print "Exception: ", e

return matches
```

The intention with the debug parameter is simply to give the output of the matches codes. The function return dictionaries ({}) where the key is a code abbreviation for the particular score and the set value is 1. As a code can sometimes belong to two categories I chose to use the dictionary instead of just returning a string. Initially my plan was to include the weights, i.e. the 1 value, but later on I separated this into different functions. Below are the weighting functions. The RCS Charlsons doesn’t have any weights, just like the Elixhausers and therefore I’ve not added that one.

```def GetCharlsonWeight(charlson_code):
""" Looks for a code and returns that weight for
that charlsons code
"""
charlsons_weight = {}
charlsons_weight['MI'] = 1
charlsons_weight['CHF'] = 1
charlsons_weight['PVD'] = 1
charlsons_weight['CEVD'] = 1
charlsons_weight['DEM'] = 1
charlsons_weight['COPD'] = 1
charlsons_weight['Rheum'] = 1
charlsons_weight['PUD'] = 1
charlsons_weight['MILDLD'] = 1
charlsons_weight['DIAB_UC'] = 1
charlsons_weight['DIAB_C'] = 2
charlsons_weight['PARA'] = 2
charlsons_weight['RD'] = 2
charlsons_weight['CANCER'] = 2
charlsons_weight['METS'] = 6
charlsons_weight['MSLD'] = 3
charlsons_weight['HIV'] = 6

try:
return charlsons_weight[charlson_code]
except:
raise ValueError("The charlson code group = '{0}' was not found in weight list".format(charlson_code))

def GetElixhausersWeight(elixhauser_code):
"""All have value 1, this is just because
Charlsons has one, gives a better symmetry"""
return 1
```

Once you have looped through a patient’s all ICD-codes you want to check the hierarchy, i.e. malignancy = cancer so the score should only be counted as one. Note: this is undefined for the Elixhauser’s as it has no natural weighting although van Walraven et al’s weights can be applied.

```def Adjust4CharlsonHierarchy(icdCodes):
"""
Since metastases indicate - cancer, complicated diabetes - diabetes,
moderate to severe liver disease - mild liver disease these
variable should be cleared so that the subject doesn't get points for both.
In other words the more complicated disease is the one that counts
"""
if (len(icdCodes) == 0):
return icdCodes

if (icdCodes.has_key('METS') and icdCodes.has_key('CANCER')):
if (icdCodes['METS'] > 0):
del(icdCodes['CANCER'])

if (icdCodes.has_key('MSLD') and icdCodes.has_key('MILDLD')):
if (icdCodes['MSLD'] > 0):
del(icdCodes['MILDLD'])

if (icdCodes.has_key('DIAB_C') and icdCodes.has_key('DIAB_UC')):
if (icdCodes['DIAB_C'] > 0):
del(icdCodes['DIAB_UC'])

return icdCodes

"""
Since metastases indicate - cancer, complicated diabetes - diabetes,
moderate to severe liver disease - mild liver disease these
variable should be cleared so that the subject doesn't get points for both.
In other words the more complicated disease is the one that counts
"""
if (len(icdCodes) == 0):
return icdCodes

if (icdCodes.has_key('METS') and icdCodes.has_key('CANCER')):
if (icdCodes['METS'] > 0):
del(icdCodes['CANCER'])

return icdCodes

"""
Since metastases indicate - cancer, complicated diabetes - diabetes,
complicated hypertension - hypertension these
variable should be cleared so that the subject doesn't get points for both.
In other words the more complicated disease is the one that counts
"""
if (len(icdCodes) == 0):
return icdCodes

if (icdCodes.has_key('METS') and icdCodes.has_key('Tumor')):
if (icdCodes['METS'] > 0):
del(icdCodes['Tumor'])

if (icdCodes.has_key('HPTN_C') and icdCodes.has_key('HPTN_UC')):
if (icdCodes['HPTN_C'] > 0):
del(icdCodes['HPTN_UC'])

if (icdCodes.has_key('Diab_C') and icdCodes.has_key('Diab_UC')):
if (icdCodes['Diab_C'] > 0):
del(icdCodes['Diab_UC'])

# Blood loss anemia and deficiency anemia
# are regarded as uncorrelated

return icdCodes
```

For generating the variable labels in SPSS I have a few helper functions. These return tuples containing dictionaries that have the name & label keys, where name is the key from the find-function and the label is the label for the SPSS label.

```def GetCharlsonVdef(prefix = 'Charlsons_', charlson_score_var_name = 'CCI'):
""" Returns tuples with the charlson variables
ready to create the variables form Charlson
comorbidity index through using the spssdata append(vdef())
"""
charlson_variables = []
charlson_variables.append({'name': 'MI', 'label': 'Ch Myocardial Infarction'})
charlson_variables.append({'name': 'CHF', 'label': 'Ch Congestive Heart Failure'})
charlson_variables.append({'name': 'PVD', 'label': 'Ch Periphral Vascular Disease'})
charlson_variables.append({'name': 'CEVD', 'label': 'Ch Cerebrovascular Disease'})
charlson_variables.append({'name': 'DEM', 'label': 'Ch Dementia'})
charlson_variables.append({'name': 'COPD', 'label': 'Ch Chronic Pulmonary Disease'})
charlson_variables.append({'name': 'Rheum', 'label': 'Ch Rheumatic Disease'})
charlson_variables.append({'name': 'PUD', 'label': 'Ch Peptic Ulcer Disease'})
charlson_variables.append({'name': 'MILDLD', 'label': 'Ch Mild Liver Disease'})
charlson_variables.append({'name': 'DIAB_UC', 'label': 'Ch Diabetes without complications'})
charlson_variables.append({'name': 'DIAB_C', 'label': 'Ch Diabetes with complications'})
charlson_variables.append({'name': 'PARA', 'label': 'Ch Paraplegia and Hemiplegia'})
charlson_variables.append({'name': 'RD', 'label': 'Ch Renal Disease'})
charlson_variables.append({'name': 'CANCER', 'label': 'Ch Cancer'})
charlson_variables.append({'name': 'METS', 'label': 'Ch Metastatic Carcinoma'})
charlson_variables.append({'name': 'MSLD', 'label': 'Ch Moderate or Severe Liver Disease'})
charlson_variables.append({'name': 'HIV', 'label': 'Ch AIDS/HIV'})

return_tuple = []
return_tuple.append(spssdata.vdef(charlson_score_var_name, vlabel='Charlsons comorbidity score', vfmt=['F', 2, 0]))
for v in charlson_variables:
label = 'Charlsons: ' + v['label']
variable_name = prefix + v['name']
return_tuple.append(spssdata.vdef(variable_name, vlabel=label, vfmt=['F', 2, 0]))
return return_tuple

def GetRCSharlsonVdef(prefix = 'RCSh_', charlson_score_var_name = 'RS_CCI'):
""" Returns tuples with the royal society charlson variables
ready to create the variables form Charlson
comorbidity index through using the spssdata append(vdef())
"""
charlson_variables = []
charlson_variables.append({'name': 'MI', 'label': 'RCS Myocardial Infarction'})
charlson_variables.append({'name': 'CHF', 'label': 'RCS Congestive Heart Failure'})
charlson_variables.append({'name': 'PVD', 'label': 'RCS Periphral Vascular Disease'})
charlson_variables.append({'name': 'CEVD', 'label': 'RCS Cerebrovascular Disease'})
charlson_variables.append({'name': 'DEM', 'label': 'RCS Dementia'})
charlson_variables.append({'name': 'COPD', 'label': 'RCS Chronic Pulmonary Disease'})
charlson_variables.append({'name': 'Rheum', 'label': 'RCS Rheumatic Disease'})
charlson_variables.append({'name': 'LD', 'label': 'RCS Liver Disease'})
charlson_variables.append({'name': 'DIAB', 'label': 'RCS Diabetes'})
charlson_variables.append({'name': 'PARA', 'label': 'RCS Paraplegia and Hemiplegia'})
charlson_variables.append({'name': 'RD', 'label': 'RCS Renal Disease'})
charlson_variables.append({'name': 'CANCER', 'label': 'RCS Cancer'})
charlson_variables.append({'name': 'METS', 'label': 'RCS Metastatic Carcinoma'})
charlson_variables.append({'name': 'HIV', 'label': 'RCS AIDS/HIV'})

return_tuple = []
return_tuple.append(spssdata.vdef(charlson_score_var_name, vlabel='RS Charlsons comorbidity score', vfmt=['F', 2, 0]))
for v in charlson_variables:
label = 'Charlsons: ' + v['label']
variable_name = prefix + v['name']
return_tuple.append(spssdata.vdef(variable_name, vlabel=label, vfmt=['F', 2, 0]))
return return_tuple

def GetElixhausersVdef(prefix = 'Elix_', elixhausers_score_var_name = 'ElxCI'):
""" Returns tuples with the charlson variables
ready to create the variables form Charlson
comorbidity index through using the spssdata append(vdef())
"""
elixhausers_variables = []
elixhausers_variables.append({'name': 'CHF', 'label': 'Elx Congestive Heart Failure'})
elixhausers_variables.append({'name': 'Arrhy', 'label': 'Elx Caridiac Arrhythmia'})
elixhausers_variables.append({'name': 'VD', 'label': 'Elx Valvular Disease'})
elixhausers_variables.append({'name': 'PCD', 'label': 'Elx Pulmonary Circulation Disorders'})
elixhausers_variables.append({'name': 'PVD', 'label': 'Elx Peripheral Vascular Disorders'})
elixhausers_variables.append({'name': 'HPTN_UC', 'label': 'Elx Hypertension Uncomlicated'})
elixhausers_variables.append({'name': 'HPTN_C', 'label': 'Elx Hypertension comlicated'})
elixhausers_variables.append({'name': 'Para', 'label': 'Elx Paralysis'})
elixhausers_variables.append({'name': 'OthND', 'label': 'Elx Other Neurological Disorders'})
elixhausers_variables.append({'name': 'COPD', 'label': 'Elx Chronic Pulmonary Disease'})
elixhausers_variables.append({'name': 'Diab_UC', 'label': 'Elx Diabetes Uncomplicated'})
elixhausers_variables.append({'name': 'Diab_C', 'label': 'Elx Diabetes Complicated'})
elixhausers_variables.append({'name': 'Hptothy', 'label': 'Elx Hypothyroidism'})
elixhausers_variables.append({'name': 'RF', 'label': 'Elx Renal Failure'})
elixhausers_variables.append({'name': 'LD', 'label': 'Elx Liver Disease'})
elixhausers_variables.append({'name': 'PUD_NB', 'label': 'Elx Peptic Ulcer Disease excluding bleeding'})
elixhausers_variables.append({'name': 'HIV', 'label': 'Elx AIDS/HIV'})
elixhausers_variables.append({'name': 'Lymp', 'label': 'Elx Lymphoma'})
elixhausers_variables.append({'name': 'METS', 'label': 'Elx Metastatic Cancer'})
elixhausers_variables.append({'name': 'Tumor', 'label': 'Elx Solid Tumor without Metastasis'})
elixhausers_variables.append({'name': 'Rheum_A', 'label': 'Elx Rheumatoid Arthsitis/collagen'})
elixhausers_variables.append({'name': 'Coag', 'label': 'Elx Coagulopathy'})
elixhausers_variables.append({'name': 'Obesity', 'label': 'Elx Obesity'})
elixhausers_variables.append({'name': 'WL', 'label': 'Elx Weight Loss'})
elixhausers_variables.append({'name': 'Fluid', 'label': 'Elx Fluid and Ecletrolyte Disorders'})
elixhausers_variables.append({'name': 'BLA', 'label': 'Elx Blood Loss Anemia'})
elixhausers_variables.append({'name': 'DA', 'label': 'Elx Deficiency Anemia'})
elixhausers_variables.append({'name': 'Alcohol', 'label': 'Elx Alcohol Abuse'})
elixhausers_variables.append({'name': 'Drug', 'label': 'Elx Drug Abuse'})
elixhausers_variables.append({'name': 'Psycho', 'label': 'Elx Psychoses'})
elixhausers_variables.append({'name': 'Dep', 'label': 'Elx Depression'})

return_tuple = []
return_tuple.append(spssdata.vdef(elixhausers_score_var_name, vlabel='Elixhausers comorbidity score', vfmt=['F', 2, 0]))
for v in elixhausers_variables:
label = 'Elixhausers: ' + v['label'].strip()
variable_name = prefix + v['name']
return_tuple.append(spssdata.vdef(variable_name, vlabel=label, vfmt=['F', 2, 0]))
return return_tuple

```

In case you are working with a Swedish dataset I have this translation function for Swedish ICD-9 codes where a letter takes on the fourth position:

```def TranslateFromSwedishIcd9(icd):
"""
Swedish ICD 9 has a letter as 4:th variable and therefore this
variable needs to be replaced with the true numeric value
"""
if (re.match("[EV0-9][0-9]{2}[ABCDEFGHXW]", icd)):
letter = icd[3:4].upper()
translate_dict = {
"A": "0",
"B": "1",
"C": "2",
"D": "3",
"E": "4",
"F": "5",
"G": "6",
"H": "7",
"W": "8",
"X": "9"
}

icd_list = list(icd)
icd_list[3] = translate_dict[letter]
return "".join(icd_list)
else:
return icd
```

As these are just the basic functions for the scores I’ve also written a post about how to glue it all together.

### 4 Responses to Comorbidity measures

1. JN Gaetano says:

I am a physician trying to implement comorbidity software using SPSS, and a beginner to using R and Python plug-ins. I consider myself otherwise proficient in basic SPSS. Having problems with knowing “where” to put the function code and “wx library needs to be installed and loaded, se the collapsed code block below.” I guess I just dont know how to build a format library?? and how to implement it? Any help would be much appreciated.

• Max Gordon says:

I would actually advise against using SPSS’ Python plug-in as it currently has a serious bug (at least when I reported the bug in May). I don’t think my script will work adequately.

I have recently developed a new package that builds upon the SPSS code and that is validated on the same principles, you can find it on Github here. Just use the devtools package to install it. I’ll update this page soon to match that package, I just haven’t had time.

• JN Gaetano says:

Thank you for your reply. I’ve successfully installed your icd10.comorbidities package via devtools and am ready to use it with my dataset (the HCUP Nationwide Inpatient Sample, released by the AHRQ).

I’m now stuck at entering the appropriate arguments for the cmrbdt.calc function. The ‘ds’ argument would be my active dataset in SPSS, but not sure how to point ‘ds’ there. My id_column would be a variable “KEY_NIS”, while my icd_columns are “DX1” to “DX25”

Any hints to get me going? Apologize for my R ignorance, any help greatly appreciated…

JNG

• JN Gaetano says:

Nevermind…figured it out…not sure if this is the best way, but works:

```x < - spssdata.GetDataFromSPSS(variables="DX1 to DX25")
x <- as.data.frame(x)
y <- cmrbdt.calc(x, cmrbdt.finder_fn=cmrbdt.finder.regex.elixhauser_Quan2005, cmrbdt.finder_hierarchy_fn=hierarchy.elixhauser_Quan2005, cmrbdt.weight_fn=weight.Elixhausers.VanWalraven2009)

dict <- spssdictionary.GetDictionaryFromSPSS()
casedata <- spssdata.GetDataFromSPSS()
varSpec <- c('ElixScore','Elixhauser Score',0,'F8','scale')
dict <- data.frame(dict,varSpec)
spssdictionary.SetDictionaryToSPSS('results',dict)
casedata <- data.frame(casedata,y\$score)
spssdata.SetDataToSPSS('results',casedata)
spssdictionary.EndDataStep()
```