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

add option to return score test components #100

Merged
merged 4 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
15 changes: 14 additions & 1 deletion R/emuFit.R
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
#' @param trackB logical: should values of B be recorded across optimization
#' iterations and be returned? Primarily used for debugging. Default is FALSE.
#' @param return_nullB logical: should values of B under null hypothesis be returned. Primarily used for debugging. Default is FALSE.
#' @param return_score_components logical: should components of score statistic be returned? Primarily used for debugging. Default is FALSE.
#' @param return_both_score_pvals logical: should score p-values be returned using both
#' information matrix computed from full model fit and from null model fits? Default is
#' FALSE. This parameter is used for simulations - in any applied analysis, type of
Expand Down Expand Up @@ -156,6 +157,7 @@ emuFit <- function(Y,
max_step = 1,
trackB = FALSE,
return_nullB = FALSE,
return_score_components = FALSE,
return_both_score_pvals = FALSE,
remove_zero_comparison_pvals = 0.01,
unobserved_taxon_error = TRUE) {
Expand Down Expand Up @@ -485,6 +487,10 @@ and the corresponding gradient function to constraint_grad_fn.")
gap = NA,
converged = NA)

if (return_score_components) {
score_components <- vector(mode = "list", length = nrow(test_kj))
}

if (return_both_score_pvals) {
colnames(coefficients)[colnames(coefficients) == "pval"] <-
"score_pval_full_info"
Expand Down Expand Up @@ -545,6 +551,10 @@ and the corresponding gradient function to constraint_grad_fn.")
return_both_score_pvals = return_both_score_pvals,
cluster = cluster)

if (return_score_components & !(is.null(test_result))) {
score_components[[test_ind]] <- test_result$score_pieces
}

if (is.null(test_result)) {
if (return_nullB) {
nullB_list[[test_ind]] <- NA
Expand Down Expand Up @@ -593,7 +603,7 @@ and the corresponding gradient function to constraint_grad_fn.")
p = p,
I_inv=I_inv,
Dy = just_wald_things$Dy,
cluster = cluster)
cluster = cluster)$score_stat


which_row <- which((as.numeric(coefficients$k) == as.numeric(test_kj$k[test_ind]))&
Expand Down Expand Up @@ -745,6 +755,9 @@ and the corresponding gradient function to constraint_grad_fn.")
warning("Optimization for estimation under the null for robust score tests failed to converge for some tests. See 'null_estimation_unconverged' within the returned emuFit object for which tests are affected by this.")
}
}
if (run_score_tests & return_score_components) {
results$score_components <- score_components
}

return(structure(results, class = "emuFit"))
}
Expand Down
2 changes: 1 addition & 1 deletion R/get_score_stat.R
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ get_score_stat <- function(Y,
inside <- Matrix::crossprod(I_inv_H, Dy) %*% I_inv_H
score_stat <- as.numeric(as.matrix(outside^2/inside))*score_adj

return(as.numeric(score_stat))
return(list(score_stat = as.numeric(score_stat), outside = outside, inside = inside, score = score))
}
18 changes: 15 additions & 3 deletions R/score_test.R
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ retrying with smaller penalty scaling parameter tau and larger inner_maxit.")
#indexes in long format corresponding to the j_constr-th col of B
#get score stat
indexes_to_remove <- (j_ref - 1)*p + 1:p
score_stat <- try(
score_res <- try(
get_score_stat(Y = Y,
X_cup = X_cup,
X = X,
Expand All @@ -202,6 +202,11 @@ retrying with smaller penalty scaling parameter tau and larger inner_maxit.")
I_inv = I_inv,
Dy = Dy,
cluster = cluster))
if (inherits(score_res, "try-error")) {
score_stat <- score_res
} else {
score_stat <- score_res$score_stat
}

if(!return_both_score_pvals){ #typically we want only one score p-value
#(using only one version of information matrix)
Expand All @@ -210,6 +215,7 @@ retrying with smaller penalty scaling parameter tau and larger inner_maxit.")
score_stat <- NA
}
return(list("score_stat" = score_stat,
"score_pieces" = score_res,
"pval" = pchisq(score_stat,1,lower.tail = FALSE),
"log_pval" = pchisq(score_stat,1,lower.tail = FALSE, log.p = TRUE),
"niter" = constrained_fit$niter,
Expand All @@ -226,7 +232,7 @@ retrying with smaller penalty scaling parameter tau and larger inner_maxit.")
} else{
#for simulations -- if we want to return both the score p-value using
#information from full model fit and from null model
score_stat_with_null_info <-
score_res_with_null_info <-
get_score_stat(Y = Y,
X_cup = X_cup,
X = X,
Expand All @@ -241,17 +247,23 @@ retrying with smaller penalty scaling parameter tau and larger inner_maxit.")
p = p,
I_inv = NULL,
Dy = Dy)

if (inherits(score_res_with_null_info, "try-error")) {
score_stat_with_null_info <- score_res_with_null_info
} else {
score_stat_with_null_info <- score_res_with_null_info$score_stat
}
score_stat_with_null_info <- score_stat_with_null_info
if (inherits(score_stat_with_null_info, "try-error")) {
warning("one of the score statistics for test of k = ", k_constr, " and j = ", j_constr, " cannot be computed, likely because the information matrix is computationally singular.")
score_stat_with_null_info <- NA
}

return(list("score_stat" = score_stat,
"score_pieces" = score_res,
"pval" = pchisq(score_stat,1,lower.tail = FALSE),
"log_pval" = pchisq(score_stat,1,lower.tail = FALSE, log.p = TRUE),
"score_stat_null_info" = score_stat_with_null_info,
"score_pieces_null_info" = score_res_with_null_info,
"pval_null_info" = pchisq(score_stat_with_null_info,1,lower.tail = FALSE),
"log_pval_null_info" = pchisq(score_stat_with_null_info,1,lower.tail = FALSE,log.p = TRUE),
"niter" = constrained_fit$niter,
Expand Down
3 changes: 3 additions & 0 deletions man/emuFit.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions tests/testthat/test-emuFit.R
Original file line number Diff line number Diff line change
Expand Up @@ -640,3 +640,30 @@ test_that("emuFit works with fitted objects passed in", {
})

})

test_that("emuFit has 'score_components' object when `return_score_componments = T`", {
mod <- emuFit(Y = Y,
X = X,
verbose = FALSE,
B_null_tol = 1e-2,
tolerance = 0.01,
tau = 2,
return_wald_p = FALSE,
compute_cis = FALSE,
run_score_tests = TRUE,
test_kj = data.frame(k = 2, j = 1),
return_score_components = T)
expect_true("score_components" %in% names(mod))
mod <- emuFit(Y = Y,
X = X,
verbose = FALSE,
B_null_tol = 1e-2,
tolerance = 0.01,
tau = 2,
return_wald_p = FALSE,
compute_cis = FALSE,
run_score_tests = TRUE,
test_kj = data.frame(k = 2, j = 1),
return_score_components = F)
expect_false("score_components" %in% names(mod))
})
8 changes: 4 additions & 4 deletions tests/testthat/test-get_score_stat.R
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ test_that("Robust score statistic is invariant to reference taxon", {
n = n,
p = p,
I = NULL,
Dy = NULL)
Dy = NULL)$score_stat
)

expect_true(sd(score_stats)<1e-5)
Expand Down Expand Up @@ -193,7 +193,7 @@ under null when Poisson assumption is met", {
c1 = c1,
maxit = maxit,
inner_maxit = inner_maxit,
verbose = FALSE)
verbose = FALSE)$score_stat

j_ref <- 5

Expand All @@ -212,7 +212,7 @@ under null when Poisson assumption is met", {
check_influence = FALSE,
I = NULL,
Dy = NULL,
model_based = FALSE)
model_based = FALSE)$score_stat

x <- seq(-10,5,0.01)
# hist(log(score_stats[1:sim]),breaks = 20,freq = FALSE)
Expand Down Expand Up @@ -329,7 +329,7 @@ test_that("model-based score statistic is invariant to reference taxon", {
n = n,
p = p,
I = NULL,
Dy = NULL)
Dy = NULL)$score_stat
})

expect_true(sd(score_stats)<1e-8)
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-score_test.R
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ we do *not* get same results if we use incorrect info", {
J = J,
n = n,
p = p,
I_inv = I_inv)
I_inv = I_inv)$score_stat

score_stat_with_other_mat <-
get_score_stat(Y = Y_aug,
Expand All @@ -102,7 +102,7 @@ we do *not* get same results if we use incorrect info", {
J = J,
n = n,
p = p,
I_inv = diag(rep(1,18)))
I_inv = diag(rep(1,18)))$score_stat

expect_equal(score_stat_with_I_inv,score_test_as_is$score_stat)
expect_true(score_stat_with_other_mat !=score_test_as_is$score_stat)
Expand Down
Loading