GitHub

ATM (package name: AgeTopicModels)

Age-dependent topic modelling (ATM) is a method for inferring comorbidity profiles for individuals at Biobank Scale. Details of the Method is available in the paper Age-dependent topic modelling of comorbidities in UK Biobank identifies disease subtypes with differential genetic risk.

ATM assigns to each individual topic weights for several disease topics; each disease topic reflects a set of diseases that tend to co-occur as a function of age, quantified by age-dependent topic loadings for each disease. The model assumes that for each disease diagnosis, a topic is sampled based on the individual’s topic weights (which sum to 1 across topics, for a given individual), and a disease is sampled based on the individual’s age and the age-dependent topic loadings (which sum to 1 across diseases, for a given topic at a given age). The model generalises the latent dirichlet allocation (LDA) model by allowing topic loadings for each topic to vary with age. My Image

For bug reports, please email: xilinjiang@hsph.harvard.edu.

Note: ATM is designed for identifying disease subtypes and infer comorbidity trajectories, but not for performing GWAS (due to the likelihood structure). For GWAS we recommend using LFA, see GWAS using Latent Feature Allocation (LFA).

Update log

September 15th, 2025: ATM now can be run when age information is not available. In that case ATM is reduced to the LDA model. As the LDA model are implemented using collapsed variational inference, it theoretically are more accurate than most implementation that uses mean field variational inference.

Imputing for missing age (age_imputation) is also available -- users can use the imputation procedure when they have missing age information.

Installation

You can install the development version of ATM from GitHub with:

# install.packages("devtools")
devtools::install_github("Xilin-Jiang/ATM")

Quick start

Run ATM on diagnosis data to infer topic loadings and topic weights from diagnosis data. Note that runing ATM on 100K individuals would take ~30min (default number of inference is 5 runs; the function will pick the best fit). If the data set is too small for inferring its disease topics and the goal is to infer patient-level topic weights (i.e. assign comorbidity profiles to individuals based on the set of diseases they have), please use loading2weights. The input data should be format data as HES_age_example; first column is individual ID, second column is the disease code; third column is the age-at-diagnosis.

Note for each individual, we only keep the first onset of each diseases. Therefore, if there are recurrent incidences of the same disease code for the same individual, the rest will be ignored.

library(AgeTopicModels)
# head(HES_age_example)
HES_age_small_sample <- dplyr::slice_sample(HES_age_example, prop = 0.1)
ATM_results <- wrapper_ATM(HES_age_example, 10, CVB_num = 1)
# individual comorbidity weights
subtypes_atm <- data.frame(individual_id = ATM_results$patient_list, topic_weights = ATM_results$topic_weights)
# visualise topic loadings
topic_id <- 1 # topic id
disease_names <- dplyr::left_join(ATM_results$ds_list, disease_info_phecode_icd10,
                    by = c("diag_icd10" = "phecode"),relationship = "many-to-one")
plot_age_topics(disease_names = disease_names$phenotype,
        trajs = ATM_results$topic_loadings[,,topic_id])

The key output from the data is the comorbidity weights ("topic weights"). Using above code subtypes_atm will be the patient-level comorbidity weights that summarise comorbidity information of each individual.

You can also visualise the pre-trained comorbidity profiles (topic loadings), use plot_age_topics function. Details are provided in Visualise the comorbidity topic loadings section.

disease_list <- UKB_349_disease %>%
  dplyr::left_join(disease_info_phecode_icd10, by = c("diag_icd10"="phecode" )) %>%
  dplyr::pull(phenotype)
topic_id <- 1 # topic id
plot_age_topics(disease_names = disease_list,
        trajs = UKB_HES_10topics[30:80,,topic_id])

The key estimand for ATM is the comorbidity weights (topic weights) for each individual. Topic weights represent an individual-level loads of the comorbidity profiles, which can be used to identify disease subtypes or measure the comorbidity burden. If the goal is obtaining the topic weights for a group of individuals to learn about their comorbidity profile, there is no need to infer the comorbidity topic loadings. Following code below to map the example diagnosis history (example data HES_age_example) to the optimal disease topics inferred from UK Biobank HES data. Details are in Inferring comorbidity profiles for individuals section.

new_weights <- loading2weights(HES_age_example, ds_list = UKB_349_disease, topics = UKB_HES_10topics)

UKB_HES_10topics is an internal dataset containing topic loadings inferred from 349 diseases in the UK Biobank HES data. You could substitute it to disease topics inferred from other populations, with the same data format (a tensor of shape

Read the original on github.com ↗