# mutual information for testing set enrichment?

I've created a process that associates members of two sets, specifically codes from the International Classification of Diseases (ICD) hierarchy and the semantically richer Monarch Disease Ontology (MonDO). (MonDO already does something similar, but my method also associates ICD codes that have a path to a MonDO term via other terms in a linked data cloud.)

I would like to find the MonDO association that is most enriched for each ICD term. (One ICD code can be associated with multiple MonDO terms, and vice versa. ) I have started with a "hammer and nail" approach that's familiar to me: a hypergeometric calculation like one would use for gene set enrichment(1,2), except I'm calculating a test statistic with R's dnorm instead of testing hypotheses and returning p-values.

I have some subjective comfort with the hypergeometric approach (see below), but my boss (a genetics professor) would like me to try an information entropy or mutual information approach. I have no idea how to get started with that. My reading has led me to believe that mutual information is about the relationship between two variables, not between specific levels of those variables. Along those lines, R's infotheo::mutinformation and widyr::pairwise_pmi both seem to return summary statistics for the dataset, not an assessment of each association.

### Hypergeometric reality check:

For the ICD associations that I've spot checked, the MonDO term with the lowest hypergeometric statistic generally has the best semantic alignment (subjectively speaking), even if the lexical similarity is low. For example, my process finds the following associations from ICD9CM:250.4, "Diabetes with renal manifestations":

+---------------+----------------+--------------------------------------+
|  MonDO.term   | hyperg.density |             MonDO.label              |
+---------------+----------------+--------------------------------------+
| MONDO:0005016 |     -7.8638915 | diabetic nephropathy                 |
| MONDO:0005015 |     -4.0628001 | diabetes mellitus (disease)          |
| MONDO:0005240 |     -4.0516889 | kidney disease                       |
| MONDO:0002908 |     -4.0406997 | glucose metabolism disease           |
| MONDO:0037792 |     -3.9797537 | carbohydrate metabolism disease      |
| MONDO:0020595 |     -3.5348043 | disease of retroperitoneum           |
| MONDO:0002118 |     -3.4197708 | urinary system disease               |
| MONDO:0005066 |     -3.2170997 | metabolic disease                    |
| MONDO:0005151 |     -3.1992739 | endocrine system disease             |
| MONDO:0021145 |     -2.4329025 | disease of genitourinary system      |
| MONDO:0044965 |     -1.9260256 | abdominal and pelvic region disorder |
| MONDO:0021199 |     -0.1740629 | disease by anatomical system         |
| MONDO:0024505 |     -0.1172667 | disorder by anatomical region        |
+---------------+----------------+--------------------------------------+


I'm modelling this as an urn that contains one ball for each ICD code. Each ball is annotated with one or more MonDO terms. Referring to R's formula

dval <- dhyper(x, m, n, k)


I'm using 1 for both x and k, because I know that I'm drawing one known ICD code, and testing for the enrichment of a MonDO term that my method has associated. N is the total number of ICD codes that have been associated with at least one MonDO code, m is the total number of the associated ICD codes that have been specifically associated with a given MonDO code, and n = N - m.

1/(total number of associated ICD terms)

We'll probably scale or normalize that by some constant, but even without any normalization, it generates subjectively reasonable rankings like the ones for ICD9CM:250.4, "Diabetes with renal manifestations", in the question.