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

2: Minimum prototype for pilot #4

Merged
merged 58 commits into from
Nov 16, 2022
Merged
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
d15ed14
start with clean slated package
Sep 26, 2022
1d8089a
first stab at fit_gee
Sep 26, 2022
3045179
first functional lsmeans table
Sep 28, 2022
f4046f6
Merge 30451795e12580f177dc1aa705e58d1e5ab9a832 into e1410f811e6f25dee…
danielinteractive Sep 28, 2022
935b267
[skip actions] Restyle files
github-actions[bot] Sep 28, 2022
ae3066d
trigger checks
Sep 29, 2022
6f482a8
fix dependencies
Oct 3, 2022
fa3d1bb
Add tern as an upstream repo
cicdguy Oct 3, 2022
c6512c3
Add nestcolor as a dep
cicdguy Oct 3, 2022
60c9f73
Add tern
cicdguy Oct 3, 2022
e6a87a0
Update staged_dependencies.yaml
danielinteractive Oct 3, 2022
de93fae
Add nestcolor to DESCRIPTION
walkowif Oct 6, 2022
03a900d
fix build_formula when there are no covariates
Oct 10, 2022
3e45c01
assert arm factor, fix ci for coef table
Oct 10, 2022
3c39a70
Merge remote-tracking branch 'origin/add-tern-to-sd' into 2_prototype
Oct 20, 2022
8f0362b
Merge 3c39a705854649919d8b4aa3a26ff4751f92958d into e1410f811e6f25dee…
danielinteractive Oct 20, 2022
2a510d0
[skip actions] Restyle files
github-actions[bot] Oct 20, 2022
2df6402
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 20, 2022
eb97e43
Merge branch '2_prototype' of https://github.com/insightsengineering/…
dependabot-preview[bot] Oct 20, 2022
dd5e7e0
add the VarCorr part
Oct 21, 2022
9ae5c2e
Merge dd5e7e04fc6aa3bffba737c17724db46ce609368 into e1410f811e6f25dee…
danielinteractive Oct 21, 2022
9435fc8
[skip actions] Restyle files
github-actions[bot] Oct 21, 2022
6b0e838
compare with SAS
Oct 21, 2022
89ec09d
Merge remote-tracking branch 'origin/2_prototype' into 2_prototype
Oct 21, 2022
8bb6d31
Merge 89ec09dab3bb81a3d1612b5c02c280fbf36e10c9 into e1410f811e6f25dee…
danielinteractive Oct 21, 2022
7eb8190
[skip actions] Restyle files
github-actions[bot] Oct 21, 2022
828b243
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Oct 21, 2022
46a491f
Merge branch '2_prototype' of https://github.com/insightsengineering/…
dependabot-preview[bot] Oct 21, 2022
421ff8e
Merge branch 'main' into 2_prototype
edelarua Oct 25, 2022
51a28bd
Remove dummy function/test
edelarua Oct 26, 2022
393c4e9
Update pkgdown site (#15)
edelarua Oct 28, 2022
07cc990
10 Add unit tests (#17)
edelarua Nov 2, 2022
ad22982
9 Update documentation, add examples (#16)
edelarua Nov 2, 2022
b3a344f
Update README (#18)
edelarua Nov 9, 2022
51d6dd8
Update project status badge
edelarua Nov 9, 2022
fba5cd1
close #22
shajoezhu Nov 11, 2022
afffbe7
include tmc downstream
shajoezhu Nov 11, 2022
774e97f
21 Update README with example (#23)
edelarua Nov 15, 2022
3db2fa9
Add Joe and Emily as authors
edelarua Nov 15, 2022
90645eb
Merge remote-tracking branch 'origin/2_prototype' into 2_prototype
edelarua Nov 15, 2022
ee82ac4
Merge branch 'main' into 2_prototype
edelarua Nov 15, 2022
c872cf3
Merge ee82ac4a547c44a160ea22fe5edbc646a51f783d into b3a0fa247f4f57539…
danielinteractive Nov 15, 2022
f8ec995
[skip actions] Restyle files
github-actions[bot] Nov 15, 2022
a705d70
Fix spelling, fix lint
edelarua Nov 15, 2022
9fcfb1a
Merge remote-tracking branch 'origin/2_prototype' into 2_prototype
edelarua Nov 15, 2022
ee445b5
Fix lint
edelarua Nov 15, 2022
0587a3f
[skip actions] Roxygen Man Pages Auto Update
dependabot-preview[bot] Nov 15, 2022
cc6e6a4
Add nestcolor dependency, remove unused imports
edelarua Nov 15, 2022
52c7ca6
Fix spelling
edelarua Nov 15, 2022
b87db54
Update DESCRIPTION
edelarua Nov 15, 2022
a6445ce
Update description
edelarua Nov 15, 2022
90aac45
Fix warnings/notes, remove nestcolor dependency
edelarua Nov 16, 2022
4263b98
Fix error
edelarua Nov 16, 2022
c2018e1
Remove plumber
edelarua Nov 16, 2022
6439824
removing as cran + adding emmeans deps
arkadiuszbeer Nov 16, 2022
3c2a38b
Merge remote-tracking branch 'origin/2_prototype' into 2_prototype
edelarua Nov 16, 2022
d61ba74
Update docs
edelarua Nov 16, 2022
52dbb2a
Remove duplicate import
edelarua Nov 16, 2022
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
40 changes: 25 additions & 15 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,29 +1,39 @@
Type: Package
Package: tern.gee
Title: TLGs using Generalized Estimating Equations (GEE)
Version: 0.0.0.9001
Date: 2022-08-22
Authors@R:
person("insightsengineering", , , "insightsengineering@example.com", role = c("aut", "cre"))
Description: Create TLGs using Generalized Estimating Equations (GEE).
Title: Tables and Graphs for Generalized Estimating Equations (GEE) Model
Fits
Version: 0.0.0.9002
Date: 2022-10-25
Authors@R: c(
person("Daniel", "Sabanés Bové", , "daniel.sabanes_bove@roche.com", role = c("aut", "cre")),
person("F. Hoffmann-La Roche AG", role = c("cph", "fnd"))
)
Description: Create tables and graphs for GEE model fits.
License: Apache License 2.0 | file LICENSE
URL: https://github.com/insightsengineering/tern.gee/
BugReports: https://github.com/insightsengineering/tern.gee/issues
Depends:
R (>= 3.6)
R (>= 4.0),
tern (>= 0.7.9)
Imports:
plumber,
shiny,
stringr
checkmate,
geeasy,
geepack,
nlme,
rtables,
stats,
formatters,
rtables
Suggests:
future,
httr,
knitr,
shinytest,
testthat (>= 2.0)
rmarkdown,
testthat (>= 3.1),
vdiffr
VignetteBuilder:
knitr
biocViews:
Remotes:
insightsengineering/tern@*release
Config/testthat/edition: 3
Encoding: UTF-8
Language: en-US
LazyData: true
Expand Down
23 changes: 19 additions & 4 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Generated by roxygen2: do not edit by hand

export(hello)
export(plumber_api)
export(shiny_app)
importFrom(utils,packageName)
S3method(QIC,tern_gee)
S3method(VarCorr,tern_gee)
S3method(as.rtable,tern_gee)
S3method(lsmeans,tern_gee_logistic)
export(a_lsmeans_logistic)
export(as.rtable)
export(fit_gee)
export(lsmeans)
export(s_lsmeans_logistic)
export(summarize_gee_logistic)
import(checkmate)
import(rtables)
importFrom(gee,gee)
importFrom(geepack,QIC)
importFrom(nlme,VarCorr)
importFrom(rtables,add_colcounts)
importFrom(stats,acf)
importFrom(tern,as.rtable)
importFrom(tern,f_conf_level)
9 changes: 6 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# tern.gee 0.0.0.9001
### New features
# tern.gee 0.0.0.9002

* New package
### Miscellaneous

* Initialize the package.
* Update pkgdown site and README, add unit tests.
* Add examples for `fit_gee`, `lsmeans`, `s_lsmeans_logistic`, `summarize_gee_logistic`.
15 changes: 15 additions & 0 deletions R/data.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#' Example dataset for `tern.gee` package.
#'
#' Measurements of FEV1 (forced expired volume in one second) is a measure of
#' how quickly the lungs can be emptied.
#' Low levels of FEV1 may indicate chronic obstructive pulmonary disease (COPD).
#' @format A `tibble` with 800 rows and 7 variables:
#'
#' - `USUBJID`: price, in US dollars.
#' - `AVISIT`: visit number.
#' - `ARMCD`: treatment, `TRT` or `PBO`.
#' - `RACE`: 3-category race.
#' - `SEX`: sex.
#' - `FEV1_BL`: FEV1 at baseline (%).
#' - `FEV1`: FEV1 at study visits.
"fev_data"
157 changes: 157 additions & 0 deletions R/fit_gee.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
vars_gee <- function(response = "AVAL",
covariates = c(),
id = "USUBJID",
arm = "ARM",
visit = "AVISIT") {
list(
response = response,
covariates = covariates,
id = id,
arm = arm,
visit = visit
)
}

#' @keywords internal
build_formula <- function(vars) {
assert_list(vars)
arm_part <- if (is.null(vars$arm)) NULL else vars$arm
rhs_formula <- paste(
c(arm_part, vars$covariates),
collapse = " + "
)
stats::as.formula(paste(
vars$response,
"~",
rhs_formula
))
}

#' @keywords internal
build_family <- function(regression) {
assert_string(regression)

result_object <- switch(regression,
logistic = stats::binomial(link = "logit"),
stop(paste("regression type", regression, "not supported"))
)

result_class <- paste0("tern_gee_", regression)

list(
object = result_object,
class = result_class,
control = geeasy::geelm.control(scale.fix = TRUE)
)
}

#' @keywords internal
build_cor_details <- function(cor_str, vars, data) {
assert_string(cor_str)
assert_list(vars)
assert_data_frame(data)

result_str <- switch(cor_str,
"unstructured" = "unstructured",
"toeplitz" = "m-dependent",
"compound symmetry" = "exchangeable",
"auto-regressive" = "ar1",
stop(paste("correlation structure", cor_str, "not available"))
)

result_mv <- switch(cor_str,
"unstructured" = 1,
"toeplitz" = nlevels(data[[vars$visit]]) - 1,
"compound symmetry" = 1,
"auto-regressive" = 1
)

list(
str = result_str,
mv = result_mv
)
}

order_data <- function(data, vars) {
assert_data_frame(data)
assert_list(vars)

if (is.character(data[[vars$visit]])) {
message(paste("visit variable", vars$visit, "will be coerced to factor for ordering"))
message("order is:")
data[[vars$visit]] <- factor(data[[vars$visit]])
cat(toString(levels(data[[vars$visit]])))
}
if (is.factor(data[[vars$id]]) || is.character(data[[vars$id]])) {
data[[vars$id]] <- as.integer(as.factor(data[[vars$id]]))
}
assert_numeric(data[[vars$id]])

right_order <- order(data[[vars$id]], data[[vars$visit]])
data[right_order, ]
}

#' Fit a GEE Model
#'
#' @param vars (`list`)\cr see [vars_gee()].
#' @param data (`data.frame`)\cr input data.
#' @param regression (`string`)\cr choice of regression model.
#' @param cor_struct (`string`)\cr assumed correlation structure.
#'
#' @details The correlation structure can be:
#' * `unstructured`: No constraints are placed on the correlations.
#' * `toeplitz`: Assumes a banded correlation structure, i.e. the correlation
#' between two time points depends on the distance between the time indices.
#' * `compound symmetry`: Constant correlation between all time points.
#' * `auto-regressive`: Auto-regressive order 1 correlation matrix.
#'
#' @return Object of class `tern_gee` as well as specific to the kind of regression
#' which was used.
#' @export
#'
#' @examples
#' df <- fev_data
#' df$AVAL <- as.integer(fev_data$FEV1 > 30)
#'
#' fit_gee(vars = vars_gee(arm = "ARMCD"), data = df)
#'
#' fit_gee(vars = vars_gee(arm = "ARMCD"), data = df, cor_struct = "compound symmetry")
fit_gee <- function(vars = vars_gee(),
data,
regression = c("logistic"),
cor_struct = c("unstructured", "toeplitz", "compound symmetry", "auto-regressive")) {
formula <- build_formula(vars)

regression <- match.arg(regression)
family <- build_family(regression)

data <- order_data(data, vars)
data[[".id"]] <- data[[vars$id]]
data[[".waves"]] <- as.integer(data[[vars$visit]])

cor_struct <- match.arg(cor_struct)
cor_details <- build_cor_details(cor_struct, vars, data)

fit <- geeasy::geelm(
formula = formula,
id = .id,
waves = .waves,
data = data,
family = family$object,
corstr = cor_details$str,
Mv = cor_details$mv,
control = family$control
)

fit$qic <- geepack::QIC(fit)
fit$visit_levels <- levels(data[[vars$visit]])
fit$vars <- vars
fit$data <- data
assert_factor(data[[vars$arm]])
fit$ref_level <- levels(data[[vars$arm]])[1L]

structure(
fit,
class = c(family$class, "tern_gee", class(fit))
)
}
45 changes: 45 additions & 0 deletions R/gee_methods.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#' Methods for GEE Models
#'
#' Additional methods which can simplify working with the GEE result object.
#' @name gee_methods
NULL

#' @rdname gee_methods
#' @importFrom nlme VarCorr
#' @exportS3Method
VarCorr.tern_gee <- function(x, sigma = 1, ...) {
dim_mat <- length(x$visit_levels)
tmp <- id_mat <- diag(dim_mat)
corest <- x$geese$alpha

# Start with lower-triangular matrix part.
lower_mat <- switch(x$corstr,
unstructured = , # Since this is the same as exchangeable, we can do this.
exchangeable = {
tmp[lower.tri(tmp)] <- corest
tmp
},
ar1 = {
row_col_diff <- row(tmp) - col(tmp)
tmp[lower.tri(tmp)] <- corest^(row_col_diff[lower.tri(row_col_diff)])
tmp
},
`m-dependent` = {
row_col_diff <- row(tmp) - col(tmp)
tmp[lower.tri(tmp)] <- corest[row_col_diff[lower.tri(row_col_diff)]]
tmp
}
)

# Construct the full symmetric matrix.
mat <- lower_mat + t(lower_mat) - id_mat
rownames(mat) <- colnames(mat) <- x$visit_levels
mat
}

#' @rdname gee_methods
#' @importFrom geepack QIC
#' @exportS3Method
QIC.tern_gee <- function(object, ...) {
object$qic
}
61 changes: 0 additions & 61 deletions R/hello.R

This file was deleted.

Loading