Skip to content

Commit

Permalink
Merge branch 'main' into 1301-feature-request-add-confidence-interval…
Browse files Browse the repository at this point in the history
…s-for-quantiles-in-surv_time
  • Loading branch information
shajoezhu committed Sep 24, 2024
2 parents f3187a9 + ceb70fc commit 761954d
Show file tree
Hide file tree
Showing 29 changed files with 980 additions and 388 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ jobs:
uses: insightsengineering/r.pkg.template/.github/workflows/test-coverage.yaml@main
secrets:
REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
with:
additional-env-vars: |
NOT_CRAN=true
linter:
if: github.event_name != 'push'
name: SuperLinter 🦸‍♀️
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ jobs:
uses: insightsengineering/r.pkg.template/.github/workflows/test-coverage.yaml@main
secrets:
REPO_GITHUB_TOKEN: ${{ secrets.REPO_GITHUB_TOKEN }}
with:
additional-env-vars: |
NOT_CRAN=true
wasm:
name: Build WASM packages 🧑‍🏭
needs: release
Expand Down
32 changes: 32 additions & 0 deletions .github/workflows/scheduled.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,26 @@ on:
schedule:
- cron: '45 3 * * 0'
workflow_dispatch:
inputs:
chosen-workflow:
description: |
Select which workflow you'd like to run
required: true
type: choice
default: rhub
options:
- rhub
- dependency-test
- branch-cleanup
- revdepcheck

jobs:
dependency-test:
if: >
github.event_name == 'schedule' || (
github.event_name == 'workflow_dispatch' &&
inputs.chosen-workflow == 'dependency-test'
)
strategy:
fail-fast: false
matrix:
Expand All @@ -24,6 +41,11 @@ jobs:
extra-deps: |
lme4 (>= 1.1-35)
branch-cleanup:
if: >
github.event_name == 'schedule' || (
github.event_name == 'workflow_dispatch' &&
inputs.chosen-workflow == 'branch-cleanup'
)
name: Branch Cleanup 🧹
uses: insightsengineering/r.pkg.template/.github/workflows/branch-cleanup.yaml@main
secrets:
Expand All @@ -34,9 +56,19 @@ jobs:
with:
issue-assignees: "shajoezhu,Melkiades,edelarua,gmbecker,ayogasekaram"
revdepcheck:
if: >
github.event_name == 'schedule' || (
github.event_name == 'workflow_dispatch' &&
inputs.chosen-workflow == 'revdepcheck'
)
name: revdepcheck ↩️
uses: insightsengineering/r.pkg.template/.github/workflows/revdepcheck.yaml@main
rhub:
if: >
github.event_name == 'schedule' || (
github.event_name == 'workflow_dispatch' &&
inputs.chosen-workflow == 'rhub'
)
name: R-hub 🌐
uses: insightsengineering/r.pkg.template/.github/workflows/rhub.yaml@main
with:
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ default_language_version:
python: python3
repos:
- repo: https://github.com/lorenzwalthert/precommit
rev: v0.4.3
rev: v0.4.3.9001
hooks:
- id: style-files
name: Style code with `styler`
Expand Down
8 changes: 5 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: tern
Title: Create Common TLGs Used in Clinical Trials
Version: 0.9.5.9022
Date: 2024-09-09
Version: 0.9.6
Date: 2024-09-20
Authors@R: c(
person("Joe", "Zhu", , "joe.zhu@roche.com", role = c("aut", "cre")),
person("Daniel", "Sabanés Bové", , "daniel.sabanes_bove@roche.com", role = "aut"),
Expand Down Expand Up @@ -63,7 +63,8 @@ Suggests:
testthat (>= 3.1.9),
withr (>= 2.0.0)
VignetteBuilder:
knitr
knitr,
rmarkdown
RdMacros:
lifecycle,
Rdpack
Expand Down Expand Up @@ -130,6 +131,7 @@ Collate:
'h_adsl_adlb_merge_using_worst_flag.R'
'h_biomarkers_subgroups.R'
'h_cox_regression.R'
'h_incidence_rate.R'
'h_km.R'
'h_logistic_regression.R'
'h_map_for_count_abnormal.R'
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export(a_count_patients_with_event)
export(a_count_patients_with_flags)
export(a_count_values)
export(a_coxreg)
export(a_incidence_rate)
export(a_length_proportion)
export(a_odds_ratio)
export(a_proportion)
Expand Down
13 changes: 9 additions & 4 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,24 @@
# tern 0.9.5.9022
# tern 0.9.6

### Enhancements
* Added `median_long`, `quantiles_lower` and `quantiles_upper` to `s_surv_time` which includes estimate and confidence interval in one statistic.
* Added `hr_long` to `s_coxph_pairwise` which includes estimate and confidence interval in one statistic.
* Added `event_free_rate_long` to `s_surv_timepoint` which includes estimate and confidence interval in one statistic.
* Added `rate_diff_long` to `s_surv_timepoint_diff` which includes estimate and confidence interval in one statistic.
* Added `errorbar_width` and `linetype` parameters to `g_lineplot`.
* Reworking of `summarize_glm_count()` documentation and all its associated functions to better describe the results and the functions' purpose.
* Added the `.formats` argument to `tabulate_rsp_subgroups` and `tabulate_survival_subgroups` to allow users to specify formats.
* Added the `riskdiff` argument to `tabulate_rsp_subgroups` and `tabulate_survival_subgroups` to allow users to add a risk difference table column, and function `control_riskdiff` to specify settings for the risk difference column.
* Added warning to `tabulate_rsp_subgroups` when `pval` statistic is selected but `df` has not been correctly generated to add p-values to the output table.
* Added `n_rate` statistic as a non-default option to `estimate_incidence_rate` which returns both number of events observed and estimated incidence rate.
* Added `n_unique` statistic as a non-default option to `estimate_incidence_rate` which returns total number of patients with at least one event observed.
* Refactored `estimate_incidence_rate` to work as both an analyze function and a summarize function, controlled by the added `summarize` parameter. When `summarize = TRUE`, labels can be fine-tuned via the new `label_fmt` argument to the same function.
* Added `fraction` statistic to the `analyze_var_count` method group.
* Improved `summarize_glm_count()` documentation and all its associated functions to better describe the results and the functions' purpose.

### Bug Fixes
* Fixed a bug in `a_surv_time` that threw an error when split only has `"is_event"`.
* Added defaults for `d_count_cumulative` parameters as described in the documentation.
* Empty levels on `g_lineplot` x-axis are not shown in either plots.
* Fixed a bug of empty levels on `g_lineplot` x-axis were not shown in either plots.
* Fixed a bug in `a_surv_time` that threw an error when split only has `"is_event"`.
* Fixed disappearing line in `g_lineplot` when using only one group or strata level.
* Fixed defaults for formats and labels in `get_formats_from_stats` and `get_labels_from_stats`.
* Fixed bug for linear scaling factor (`scale` parameter) being applied to response but not to rate in `h_glm_count` while all distributions have logarithmic link function.
Expand All @@ -26,6 +30,7 @@
* Began deprecation of the confusing functions `summary_formats` and `summary_labels`.
* Enhanced general descriptions of analyze and summarize functions throughout package documentation.
* Finalized deprecation of the `strata` and `cohort_id` arguments to `g_lineplot`.
* Moved incidence rate helper functions into a separate `h_incidence_rate.R` file.

# tern 0.9.5

Expand Down
4 changes: 4 additions & 0 deletions R/analyze_variables.R
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,10 @@ s_summary.factor <- function(x,
c(x, ifelse(dn > 0, x / dn, 0))
}
)
y$fraction <- lapply(
y$count,
function(count) c("num" = count, "denom" = dn)
)

y$n_blq <- sum(grepl("BLQ|LTR|<[1-9]|<PCLLOQ", x))

Expand Down
135 changes: 135 additions & 0 deletions R/h_incidence_rate.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#' Helper functions for incidence rate
#'
#' @description `r lifecycle::badge("stable")`
#'
#' @param control (`list`)\cr parameters for estimation details, specified by using
#' the helper function [control_incidence_rate()]. Possible parameter options are:
#' * `conf_level`: (`proportion`)\cr confidence level for the estimated incidence rate.
#' * `conf_type`: (`string`)\cr `normal` (default), `normal_log`, `exact`, or `byar`
#' for confidence interval type.
#' * `input_time_unit`: (`string`)\cr `day`, `week`, `month`, or `year` (default)
#' indicating time unit for data input.
#' * `num_pt_year`: (`numeric`)\cr time unit for desired output (in person-years).
#' @param person_years (`numeric(1)`)\cr total person-years at risk.
#' @param alpha (`numeric(1)`)\cr two-sided alpha-level for confidence interval.
#' @param n_events (`integer(1)`)\cr number of events observed.
#'
#' @return Estimated incidence rate, `rate`, and associated confidence interval, `rate_ci`.
#'
#' @seealso [incidence_rate]
#'
#' @name h_incidence_rate
NULL

#' @describeIn h_incidence_rate Helper function to estimate the incidence rate and
#' associated confidence interval.
#'
#' @keywords internal
h_incidence_rate <- function(person_years,
n_events,
control = control_incidence_rate()) {
alpha <- 1 - control$conf_level
est <- switch(control$conf_type,
normal = h_incidence_rate_normal(person_years, n_events, alpha),
normal_log = h_incidence_rate_normal_log(person_years, n_events, alpha),
exact = h_incidence_rate_exact(person_years, n_events, alpha),
byar = h_incidence_rate_byar(person_years, n_events, alpha)
)

num_pt_year <- control$num_pt_year
list(
rate = est$rate * num_pt_year,
rate_ci = est$rate_ci * num_pt_year
)
}

#' @describeIn h_incidence_rate Helper function to estimate the incidence rate and
#' associated confidence interval based on the normal approximation for the
#' incidence rate. Unit is one person-year.
#'
#' @examples
#' h_incidence_rate_normal(200, 2)
#'
#' @export
h_incidence_rate_normal <- function(person_years,
n_events,
alpha = 0.05) {
checkmate::assert_number(person_years)
checkmate::assert_number(n_events)
assert_proportion_value(alpha)

est <- n_events / person_years
se <- sqrt(est / person_years)
ci <- est + c(-1, 1) * stats::qnorm(1 - alpha / 2) * se

list(rate = est, rate_ci = ci)
}

#' @describeIn h_incidence_rate Helper function to estimate the incidence rate and
#' associated confidence interval based on the normal approximation for the
#' logarithm of the incidence rate. Unit is one person-year.
#'
#' @examples
#' h_incidence_rate_normal_log(200, 2)
#'
#' @export
h_incidence_rate_normal_log <- function(person_years,
n_events,
alpha = 0.05) {
checkmate::assert_number(person_years)
checkmate::assert_number(n_events)
assert_proportion_value(alpha)

rate_est <- n_events / person_years
rate_se <- sqrt(rate_est / person_years)
lrate_est <- log(rate_est)
lrate_se <- rate_se / rate_est
ci <- exp(lrate_est + c(-1, 1) * stats::qnorm(1 - alpha / 2) * lrate_se)

list(rate = rate_est, rate_ci = ci)
}

#' @describeIn h_incidence_rate Helper function to estimate the incidence rate and
#' associated exact confidence interval. Unit is one person-year.
#'
#' @examples
#' h_incidence_rate_exact(200, 2)
#'
#' @export
h_incidence_rate_exact <- function(person_years,
n_events,
alpha = 0.05) {
checkmate::assert_number(person_years)
checkmate::assert_number(n_events)
assert_proportion_value(alpha)

est <- n_events / person_years
lcl <- stats::qchisq(p = (alpha) / 2, df = 2 * n_events) / (2 * person_years)
ucl <- stats::qchisq(p = 1 - (alpha) / 2, df = 2 * n_events + 2) / (2 * person_years)

list(rate = est, rate_ci = c(lcl, ucl))
}

#' @describeIn h_incidence_rate Helper function to estimate the incidence rate and
#' associated Byar's confidence interval. Unit is one person-year.
#'
#' @examples
#' h_incidence_rate_byar(200, 2)
#'
#' @export
h_incidence_rate_byar <- function(person_years,
n_events,
alpha = 0.05) {
checkmate::assert_number(person_years)
checkmate::assert_number(n_events)
assert_proportion_value(alpha)

est <- n_events / person_years
seg_1 <- n_events + 0.5
seg_2 <- 1 - 1 / (9 * (n_events + 0.5))
seg_3 <- stats::qnorm(1 - alpha / 2) * sqrt(1 / (n_events + 0.5)) / 3
lcl <- seg_1 * ((seg_2 - seg_3)^3) / person_years
ucl <- seg_1 * ((seg_2 + seg_3)^3) / person_years

list(rate = est, rate_ci = c(lcl, ucl))
}
Loading

0 comments on commit 761954d

Please sign in to comment.