{"id":32207091,"url":"https://github.com/jamesmurray7/gmvjoint","last_synced_at":"2026-03-10T17:07:00.817Z","repository":{"id":64382682,"uuid":"568914943","full_name":"jamesmurray7/gmvjoint","owner":"jamesmurray7","description":"Generalised joint models of survival and multivariate longitudinal data","archived":false,"fork":false,"pushed_at":"2024-10-06T10:55:09.000Z","size":28051,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-12-09T09:26:44.537Z","etag":null,"topics":["glmm","joint-models","longitudinal","mixed-models","model","prediction","survival","survival-analysis"],"latest_commit_sha":null,"homepage":"","language":"R","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jamesmurray7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2022-11-21T17:22:08.000Z","updated_at":"2024-10-06T10:55:12.000Z","dependencies_parsed_at":"2023-10-15T03:37:39.851Z","dependency_job_id":"d2d43288-72b5-4743-bb51-41137679a09d","html_url":"https://github.com/jamesmurray7/gmvjoint","commit_stats":{"total_commits":266,"total_committers":2,"mean_commits":133.0,"dds":0.003759398496240629,"last_synced_commit":"68b1e180d2b978616be18d507ad5dbff52e94517"},"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jamesmurray7/gmvjoint","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmurray7%2Fgmvjoint","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmurray7%2Fgmvjoint/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmurray7%2Fgmvjoint/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmurray7%2Fgmvjoint/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jamesmurray7","download_url":"https://codeload.github.com/jamesmurray7/gmvjoint/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jamesmurray7%2Fgmvjoint/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30343900,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T15:55:29.454Z","status":"ssl_error","status_checked_at":"2026-03-10T15:54:58.440Z","response_time":106,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["glmm","joint-models","longitudinal","mixed-models","model","prediction","survival","survival-analysis"],"created_at":"2025-10-22T05:45:45.462Z","updated_at":"2026-03-10T17:07:00.801Z","avatar_url":"https://github.com/jamesmurray7.png","language":"R","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `gmvjoint`\n\n## What is `gmvjoint`?\n\n* \"**g**eneralised\"\n* **m**ulti**v**ariate\n* **Joint** models.\n\n\n`gmvjoint` allows the user to fit joint models of survival and multivariate longitudinal data, where the \nlongitudinal sub-models are specified by generalised linear mixed models (GLMMs). The joint models \nare fit via maximum likelihood using an approximate EM algorithm first proposed by Bernhardt *et\nal*. (2015). The GLMMs are specified using the same syntax as for package `glmmTMB` (Brooks *et\nal*., 2017). The joint models themselves are then the  flexible extensions to those in e.g.\nWulfsohn and Tsiatis (1997). The user is able to simulate data under many different response\ntypes.\n\nCurrently, six families can be fit: Gaussian; Poisson; binomial; Gamma; negative binomial; and generalised Poisson. \n\n## Installation\nYou can install the latest 'official' release from CRAN in the usual way: \n```r\ninstall.packages('gmvjoint')\n```\n\nor the latest development version using `devtools`: \n```r\ndevtools::install_github('jamesmurray7/gmvjoint')\n``` \n \nMacOS users may be interested in [swapping their BLAS library](https://cran.r-project.org/bin/macosx/RMacOSX-FAQ.html#Which-BLAS-is-used-and-how-can-it-be-changed_003f) to one which provides an optimal BLAS implementation for Mac hardware (`vecLib`).\n\n## Example\nTo fit a joint model, we first need to specify the longitudinal and survival sub-models. \n\nThe longitudinal sub-model **must** be a list which contains the specification of the longitudinal process along with its random effects structure \nin the same syntax as a [glmmTMB](https://cran.r-project.org/package=glmmTMB) model (which itself is the same as the widely-used `lme4`). \nAs an example, suppose we want to fit a trivariate model on the oft-used PBC data, with a linear time-drug interaction term on albumin, a spline term on\n(logged) serum bilirubin and a linear fit on spiders, we specify\n```r\ndata(PBC)\nPBC \u003c- subset(PBC, select = c('id', 'survtime', 'status', 'drug', 'time',\n                              'serBilir', 'albumin', 'spiders'))\nPBC \u003c- na.omit(PBC) \nlong.formulas \u003c- list(\n  albumin ~ drug * time + (1 + time|id),\n  log(serBilir) ~ drug * splines::ns(time, 3) + (1 + splines::ns(time, 3)|id),\n  spiders ~ drug * time + (1|id)\n)\n```\nwhere we note interactions and spline-time fits are possible. \n \nThe survival sub-model must be set-up using `Surv()` from the [survival](https://cran.r-project.org/package=survival) package e.g.\n```r\nsurv.formula \u003c- Surv(survtime, status) ~ drug\n```\nCurrently interaction terms in the survival sub-model specification are unsupported. \n\nNow we can do the joint model call through the main workhorse function `joint`. This notably take a *list* of family arguments which **must** match-up in the desired order as the longitudinal process\nlist. We then fit our joint model via\n```r\nfit \u003c- joint(long.formulas = long.formulas, surv.formula = surv.formula, data = PBC, \n             family = list(\"gaussian\", \"gaussian\", \"binomial\"))\nsummary(fit)\n```\nwhere extra control arguments are documented in `?joint`. For certain families, we could additionally supply `disp.formulas` which specify the dispersion model for the corresponding longitudinal process. Numerous S3 methods exist for the class of object `joint` creates: `summary()`, `logLik()`, `fixef()`, `ranef()`, `fitted()`, `resid()`, and `vcov()`. LaTeX-ready tables can also be generated by S3 method `xtable()`. Data can be simulated under a host of different parameter set-ups using the `simData()` function.\n\nWe bridge from a set of joint model parameter estimates to a prognostic one by dynamic predictions `dynPred`. We can assess discriminatory capabilities of the `joint()` model fit by the `ROC` function, too.\n\n## To-do list\nCurrently the largest limitation exists with the relatively strict data structure necessary and the corresponding calls to the `joint` function. The below lists these (known) limitations and plans for relaxing.\n\n* Longitudinal information: The longitudinal time argument **must** be named `time` and the subject identifier (which we 'split' random effects by) `id`. Unsure if I will ever change these; I think a little more user pre-processing is no bad thing, when alternative would be a more crowded call to `joint`, which I wouldn't be a fan of.\n* Misc.: data must be balanced (i.e. no `NA` values); this will be fixed in a future update. For now I don't think this is the biggest issue, and recommend using `na.omit` for example. Additionally, the id variable __must__ increment by no more than one. That is, `data$id=1,1,1,2,2,2,3,3,3` is fine, but `data$id=1,1,1,1,3,3,3,4,4` is not. This is due to how data matrices are created internally and will be fixed in the future.  \nUpdate June 2023: Since calls and data are passed straight to `glmmTB`, possible to assign these unique indices `1:n`, nothing currently done with this, though. \n* Pretty-ing of progress bars using cli package (maybe...). \n\nNote I'm a PhD student, and the S3 methods (and some functions themselves) have largely arisen out of things I needed, or thought would be a good idea at some point!\n\n## References\n\nBernhardt PW, Zhang D and Wang HJ. A fast EM Algorithm for Fitting Joint Models of a Binary \nResponse to Multiple Longitudinal Covariates Subject to Detection Limits. \n*Computational Statistics and Data Analysis* 2015; **85**; 37--53\n\nMollie E. Brooks, Kasper Kristensen, Koen J. van Benthem, Arni Magnusson, Casper W. Berg, Anders\nNielsen, Hans J. Skaug, Martin Maechler and Benjamin M. Bolker (2017). glmmTMB Balances Speed and\nFlexibility Among Packages for Zero-inflated Generalized Linear Mixed Modeling. \n*The R Journal*, **9(2)**, 378-400.\n\nMurray, J and Philipson P. A fast approximate EM algorithm for joint models of survival and\nmultivariate longitudinal data. *Computational Statistics and Data Analysis* 2022\n\nWulfsohn MS, Tsiatis AA. A joint model for survival and longitudinal data\nmeasured with error. *Biometrics.* 1997; **53(1)**, 330-339.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmurray7%2Fgmvjoint","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjamesmurray7%2Fgmvjoint","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjamesmurray7%2Fgmvjoint/lists"}