| Title: | Generalized Pivotal Quantity Inference for the Youden Index |
|---|---|
| Description: | Monte Carlo simulation study of generalized pivotal quantity (GPQ) based confidence intervals for the Youden index and its optimal cut-point, following Lai, Tian and Schisterman (2012) <doi:10.1016/j.csda.2010.11.023>. |
| Authors: | Juan José Olmedilla Arregui [aut, cre] |
| Maintainer: | Juan José Olmedilla Arregui <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.1.0 |
| Built: | 2026-11-07 01:08:25 UTC |
| Source: | https://github.com/cran/gpqyouden |
for each row of a parameter data frameConvenience wrapper that applies find_mu1_from_J2 row-wise
to a data frame containing columns mu2, var1, var2
and J.
calculate_mu1_for_dataframe(df)calculate_mu1_for_dataframe(df)
df |
A data frame with columns |
A data frame with columns mu1, original_J and
theoretical_J.
df <- data.frame(mu2 = 0, var1 = 1, var2 = 1, J = c(0.4, 0.6)) calculate_mu1_for_dataframe(df)df <- data.frame(mu2 = 0, var1 = 1, var2 = 1, J = c(0.4, 0.6)) calculate_mu1_for_dataframe(df)
Returns the full factorial combination of variances, Youden index values,
and sample-size pairs used in the simulation study of Lai et al. (2012):
, ,
, , and eight
pairs.
default_param_grid()default_param_grid()
A data frame with 160 rows and columns mu2, sigma1,
sigma2, J, n1, n2, var1, var2.
generate_param_grid, run_parallel_grid
grid <- default_param_grid() dim(grid) head(grid)grid <- default_param_grid() dim(grid) head(grid)
Density of the contaminated normal mixture
dmixnorm(x, mu, sigma, p = 0.1)dmixnorm(x, mu, sigma, p = 0.1)
x |
Numeric vector. Points at which to evaluate the density. |
mu |
Numeric. Mean of the distribution. |
sigma |
Numeric. Base standard deviation. |
p |
Numeric. Contamination probability (default: 0.1). |
A numeric vector of density values.
pmixnorm, generate_mixture_sample
dmixnorm(x = seq(-3, 3, by = 1), mu = 0, sigma = 1, p = 0.1)dmixnorm(x = seq(-3, 3, by = 1), mu = 0, sigma = 1, p = 0.1)
Auxiliary function used by find_mu1_from_J2: evaluates
.
eq.J2(x, parameters, J2, model)eq.J2(x, parameters, J2, model)
x |
Numeric. Candidate value of |
parameters |
Numeric vector |
J2 |
Numeric. Target Youden index value. |
model |
Character. Currently only |
A numeric scalar.
# parameters = (mu2, sigma2, sigma1) eq.J2(x = 1.68, parameters = c(0, 1, 1), J2 = 0.6, model = "norm")# parameters = (mu2, sigma2, sigma1) eq.J2(x = 1.68, parameters = c(0, 1, 1), J2 = 0.6, model = "norm")
from the Youden index under the mixture modelNumerically solves for such that the true Youden index of two
contaminated normal mixture distributions equals J_target.
find_mu1_from_J_mixture( J_target, mu2, sigma1, sigma2, p = 0.1, tol = 1e-06, max_expand = 60 )find_mu1_from_J_mixture( J_target, mu2, sigma1, sigma2, p = 0.1, tol = 1e-06, max_expand = 60 )
J_target |
Numeric. Target Youden index value (must be in (0, 1)). |
mu2 |
Numeric. Mean of the non-diseased population. |
sigma1 |
Numeric. Base standard deviation of the diseased population. |
sigma2 |
Numeric. Base standard deviation of the non-diseased population. |
p |
Numeric. Contamination probability (default: 0.1). |
tol |
Numeric. Root-finding tolerance (default: 1e-6). |
max_expand |
Integer. Maximum number of bracket-expansion iterations (default: 60). |
A numeric scalar, or NA_real_ if the root cannot be found.
find_mu1_from_J2, J_true_mixture
find_mu1_from_J_mixture(J_target = 0.6, mu2 = 0, sigma1 = 1, sigma2 = 1, p = 0.1)find_mu1_from_J_mixture(J_target = 0.6, mu2 = 0, sigma1 = 1, sigma2 = 1, p = 0.1)
from the Youden index under the normal modelNumerically solves for the mean of the diseased population
such that the theoretical Youden index equals J2, given the
remaining parameters.
find_mu1_from_J2(J2, mu2, sigma2, sigma1, model)find_mu1_from_J2(J2, mu2, sigma2, sigma1, model)
J2 |
Numeric. Target Youden index value. |
mu2 |
Numeric. Mean of the non-diseased population. |
sigma2 |
Numeric. Standard deviation of the non-diseased population. |
sigma1 |
Numeric. Standard deviation of the diseased population. |
model |
Character. Currently only |
A numeric scalar, or NA_real_ if the root cannot be found.
J2.theoretical, find_mu1_from_J_mixture
find_mu1_from_J2(J2 = 0.6, mu2 = 0, sigma2 = 1, sigma1 = 1, model = "norm")find_mu1_from_J2(J2 = 0.6, mu2 = 0, sigma2 = 1, sigma1 = 1, model = "norm")
Draws n observations from the mixture distribution used in the
robustness study of Lai et al. (2012):
where ,
and .
generate_mixture_sample(n, mu, sigma, p = 0.1)generate_mixture_sample(n, mu, sigma, p = 0.1)
n |
Integer. Number of observations to generate. |
mu |
Numeric. Mean of the distribution. |
sigma |
Numeric. Base standard deviation (before scaling). |
p |
Numeric. Contamination probability (default: 0.1). |
A numeric vector of length n.
set.seed(1) y <- generate_mixture_sample(n = 50, mu = 0, sigma = 1, p = 0.1) summary(y)set.seed(1) y <- generate_mixture_sample(n = 50, mu = 0, sigma = 1, p = 0.1) summary(y)
Produces two wide-format tables (coverage probability only, with
as column headers), one for the Youden index and one for
the cut-point. These correspond to Tables 3 and 4 of Lai et al. (2012)
for , and to the analogous tables for other values of
.
generate_mixture_tables(results_df, p, out_dir)generate_mixture_tables(results_df, p, out_dir)
results_df |
Data frame as returned by |
p |
Numeric. Contamination probability used in the simulation (included in captions and file names). |
out_dir |
Character. Directory where the |
Invisibly NULL. Writes
table_J_mixture_p=<p>.tex and
table_c_mixture_p=<p>.tex to out_dir.
grid <- default_param_grid()[1:2, ] results <- run_parallel_grid(grid, generator = "mixture", n_mc = 10, K = 30, p = 0.1) generate_mixture_tables(results, p = 0.1, out_dir = tempdir())grid <- default_param_grid()[1:2, ] results <- run_parallel_grid(grid, generator = "mixture", n_mc = 10, K = 30, p = 0.1) generate_mixture_tables(results, p = 0.1, out_dir = tempdir())
Produces two long-format tables (coverage probability and average length,
one for the Youden index and one for the cut-point), with
as the first grouping column. These correspond to Tables 1 and 2 of
Lai et al. (2012).
generate_normal_tables(results_df, out_dir)generate_normal_tables(results_df, out_dir)
results_df |
Data frame as returned by |
out_dir |
Character. Directory where the |
Invisibly NULL. Writes table_J_normal.tex and
table_c_normal.tex to out_dir.
grid <- default_param_grid()[1:2, ] results <- run_parallel_grid(grid, n_mc = 10, K = 30) generate_normal_tables(results, out_dir = tempdir())grid <- default_param_grid()[1:2, ] results <- run_parallel_grid(grid, n_mc = 10, K = 30) generate_normal_tables(results, out_dir = tempdir())
Constructs a data frame of all combinations of the supplied parameter vectors and sample-size pairs, adding derived standard deviation columns.
generate_param_grid(var1, var2, mu2, J, n_pairs)generate_param_grid(var1, var2, mu2, J, n_pairs)
var1 |
Numeric vector. Variances for the diseased population. |
var2 |
Numeric vector. Variances for the non-diseased population. |
mu2 |
Numeric vector. Means for the non-diseased population. |
J |
Numeric vector. Target Youden index values. |
n_pairs |
Integer matrix with two columns ( |
A data frame with columns mu2, sigma1, sigma2,
J, n1, n2, var1, var2.
n_pairs <- matrix(c(10, 10, 20, 20), ncol = 2, byrow = TRUE) generate_param_grid(var1 = c(1, 2), var2 = 1, mu2 = 0, J = c(0.5, 0.7), n_pairs = n_pairs)n_pairs <- matrix(c(10, 10, 20, 20), ncol = 2, byrow = TRUE) generate_param_grid(var1 = c(1, 2), var2 = 1, mu2 = 0, J = c(0.5, 0.7), n_pairs = n_pairs)
Computes the generalized pivotal quantity for the optimal cut-point (Equations 10-11 in Lai et al., 2012).
gpq_c(R_mu1, R_mu2, R_sigma1, R_sigma2, tol = 0.01)gpq_c(R_mu1, R_mu2, R_sigma1, R_sigma2, tol = 0.01)
R_mu1 |
Numeric. GPQ realization for the mean of the diseased group. |
R_mu2 |
Numeric. GPQ realization for the mean of the non-diseased group. |
R_sigma1 |
Numeric. GPQ realization for the SD of the diseased group. |
R_sigma2 |
Numeric. GPQ realization for the SD of the non-diseased group. |
tol |
Numeric. Tolerance for the equal-variance case (default: 1e-2). |
A numeric scalar.
gpq_c(R_mu1 = 2, R_mu2 = 0, R_sigma1 = 1, R_sigma2 = 1.2)gpq_c(R_mu1 = 2, R_mu2 = 0, R_sigma1 = 1, R_sigma2 = 1.2)
Implements the GPQ algorithm of Lai et al. (2012) for a single dataset drawn from two normal populations, producing Monte Carlo realizations of the GPQs for the Youden index and its optimal cut-point.
gpq_from_sample(y1, y2, K = 250, tol = 0.01)gpq_from_sample(y1, y2, K = 250, tol = 0.01)
y1 |
Numeric vector. Observed sample from the diseased population. |
y2 |
Numeric vector. Observed sample from the non-diseased population. |
K |
Integer. Number of GPQ iterations (default: 250). |
tol |
Numeric. Tolerance for the equal-variance case in
|
A list with two numeric vectors of length K:
GPQ realizations for the Youden index.
GPQ realizations for the optimal cut-point.
Lai, C.-Y., Tian, L., & Schisterman, E. F. (2012). Exact confidence interval estimation for the Youden index and its corresponding optimal cut-point. Computational Statistics & Data Analysis, 56(5), 1103-1114.
set.seed(1) y1 <- rnorm(30, mean = 2, sd = 1) y2 <- rnorm(30, mean = 0, sd = 1) gpq <- gpq_from_sample(y1, y2, K = 100) quantile(gpq$RJ, probs = c(0.025, 0.975))set.seed(1) y1 <- rnorm(30, mean = 2, sd = 1) y2 <- rnorm(30, mean = 0, sd = 1) gpq <- gpq_from_sample(y1, y2, K = 100) quantile(gpq$RJ, probs = c(0.025, 0.975))
Computes the generalized pivotal quantity for the Youden index (Equation 12 in Lai et al., 2012).
gpq_J(R_mu1, R_mu2, R_sigma1, R_sigma2, Rc)gpq_J(R_mu1, R_mu2, R_sigma1, R_sigma2, Rc)
R_mu1 |
Numeric. GPQ realization for the mean of the diseased group. |
R_mu2 |
Numeric. GPQ realization for the mean of the non-diseased group. |
R_sigma1 |
Numeric. GPQ realization for the SD of the diseased group. |
R_sigma2 |
Numeric. GPQ realization for the SD of the non-diseased group. |
Rc |
Numeric. GPQ realization for the optimal cut-point. |
A numeric scalar in .
gpq_J(R_mu1 = 2, R_mu2 = 0, R_sigma1 = 1, R_sigma2 = 1.2, Rc = 1)gpq_J(R_mu1 = 2, R_mu2 = 0, R_sigma1 = 1, R_sigma2 = 1.2, Rc = 1)
Computes the generalized pivotal quantity for the mean of one population (Equation 7 in Lai et al., 2012).
gpq_mu(ybar, s, n, t_value)gpq_mu(ybar, s, n, t_value)
ybar |
Numeric. Observed sample mean. |
s |
Numeric. Observed sample standard deviation. |
n |
Integer. Sample size. |
t_value |
Numeric. Realization of a Student's t with |
A numeric scalar.
gpq_mu(ybar = 5, s = 1.2, n = 30, t_value = 0.5)gpq_mu(ybar = 5, s = 1.2, n = 30, t_value = 0.5)
Computes the generalized pivotal quantity for the standard deviation of one population (Equation 8 in Lai et al., 2012).
gpq_sigma(s2, v, n)gpq_sigma(s2, v, n)
s2 |
Numeric. Observed sample variance. |
v |
Numeric. Realization of a chi-squared with |
n |
Integer. Sample size. |
A numeric scalar (standard deviation scale).
gpq_sigma(s2 = 1.5, v = 28.3, n = 30)gpq_sigma(s2 = 1.5, v = 28.3, n = 30)
Numerically maximises the Youden index over all possible cut-points for two contaminated normal mixture distributions.
J_true_mixture(mu1, mu2, sigma1, sigma2, p = 0.1)J_true_mixture(mu1, mu2, sigma1, sigma2, p = 0.1)
mu1 |
Numeric. Mean of the diseased population. |
mu2 |
Numeric. Mean of the non-diseased population. |
sigma1 |
Numeric. Base standard deviation of the diseased population. |
sigma2 |
Numeric. Base standard deviation of the non-diseased population. |
p |
Numeric. Contamination probability (default: 0.1). |
A list with two elements:
The maximum Youden index.
The optimal cut-point that achieves it.
J_true_mixture(mu1 = 1.68, mu2 = 0, sigma1 = 1, sigma2 = 1, p = 0.1)J_true_mixture(mu1 = 1.68, mu2 = 0, sigma1 = 1, sigma2 = 1, p = 0.1)
Computes the true Youden index for two normal populations given their means and standard deviations.
J2.theoretical(parameters, model)J2.theoretical(parameters, model)
parameters |
Numeric vector or matrix with four columns in the order
|
model |
Character. Currently only |
A numeric vector of Youden index values, one per row of
parameters.
# (mu2, mu1, sigma2, sigma1) J2.theoretical(c(0, 1.68, 1, 1), model = "norm")# (mu2, mu1, sigma2, sigma1) J2.theoretical(c(0, 1.68, 1, 1), model = "norm")
Returns the standard deviations of the non-contaminated and contaminated components of the mixture as defined in Lai et al. (2012).
mix_sd(sigma)mix_sd(sigma)
sigma |
Numeric. Base standard deviation. |
A named numeric vector with elements sd_a
() and sd_b
().
mix_sd(sigma = 1)mix_sd(sigma = 1)
CDF of the contaminated normal mixture
pmixnorm(x, mu, sigma, p = 0.1)pmixnorm(x, mu, sigma, p = 0.1)
x |
Numeric vector. Points at which to evaluate the CDF. |
mu |
Numeric. Mean of the distribution. |
sigma |
Numeric. Base standard deviation. |
p |
Numeric. Contamination probability (default: 0.1). |
A numeric vector of cumulative probabilities.
dmixnorm, generate_mixture_sample
pmixnorm(x = 0, mu = 0, sigma = 1, p = 0.1)pmixnorm(x = 0, mu = 0, sigma = 1, p = 0.1)
Convenience wrapper around run_simulation that accepts a
single-row data frame (as returned by subsetting the output of
default_param_grid) and returns a one-row summary data frame.
run_one_row( row, generator = c("normal", "mixture"), n_mc = 200, K = 250, p = 0.1 )run_one_row( row, generator = c("normal", "mixture"), n_mc = 200, K = 250, p = 0.1 )
row |
A one-row data frame with columns |
generator |
Character. |
n_mc |
Integer. Number of Monte Carlo replications (default: 200). |
K |
Integer. Number of GPQ iterations per replication (default: 250). |
p |
Numeric. Contamination probability. Ignored when
|
A one-row data frame with columns mu2, var1,
var2, J, n1, n2, coverage_J,
length_J, coverage_c, length_c, generator,
p.
run_simulation, run_parallel_grid
row <- default_param_grid()[1, ] set.seed(1) run_one_row(row, n_mc = 10, K = 30)row <- default_param_grid()[1, ] set.seed(1) run_one_row(row, n_mc = 10, K = 30)
Uses mclapply on Unix/macOS and doParallel+foreach
on Windows.
run_parallel_grid( df_params, generator = c("normal", "mixture"), n_mc = 200, K = 250, p = 0.1, n_cores = getOption("mc.cores", 2L) )run_parallel_grid( df_params, generator = c("normal", "mixture"), n_mc = 200, K = 250, p = 0.1, n_cores = getOption("mc.cores", 2L) )
df_params |
Data frame of parameter combinations (from
|
generator |
Character. |
n_mc |
Integer. Number of Monte Carlo replications. |
K |
Integer. Number of GPQ iterations per replication. |
p |
Numeric. Mixture proportion. Ignored when
|
n_cores |
Integer. Number of parallel workers to use. Defaults to
|
A data frame with one row per parameter combination.
grid <- default_param_grid()[1:2, ] run_parallel_grid(grid, n_mc = 10, K = 30)grid <- default_param_grid()[1:2, ] run_parallel_grid(grid, n_mc = 10, K = 30)
Repeatedly draws paired samples under the normal or contaminated-mixture
model, computes GPQ-based confidence intervals for the Youden index and
its optimal cut-point via gpq_from_sample, and summarises
empirical coverage and mean interval length over n_mc replications.
run_simulation( mu2, sigma1, sigma2, J, n1, n2, n_mc = 200, K = 250, alpha = 0.05, generator = c("normal", "mixture"), p = 0.1 )run_simulation( mu2, sigma1, sigma2, J, n1, n2, n_mc = 200, K = 250, alpha = 0.05, generator = c("normal", "mixture"), p = 0.1 )
mu2 |
Numeric. Mean of the non-diseased population. |
sigma1 |
Numeric. Standard deviation of the diseased population. |
sigma2 |
Numeric. Standard deviation of the non-diseased population. |
J |
Numeric. Target (nominal) Youden index. |
n1 |
Integer. Sample size for the diseased population. |
n2 |
Integer. Sample size for the non-diseased population. |
n_mc |
Integer. Number of Monte Carlo replications (default: 200). |
K |
Integer. Number of GPQ iterations per replication, passed to
|
alpha |
Numeric. Significance level for the confidence intervals (default: 0.05, giving 95% intervals). |
generator |
Character. |
p |
Numeric. Contamination probability, used only when
|
A list with elements params (the scenario's parameters,
including the derived mu1), J and c, each a list
with coverage and mean_length.
run_one_row, run_parallel_grid
set.seed(1) run_simulation(mu2 = 0, sigma1 = 1, sigma2 = 1, J = 0.6, n1 = 20, n2 = 20, n_mc = 20, K = 50)set.seed(1) run_simulation(mu2 = 0, sigma1 = 1, sigma2 = 1, J = 0.6, n1 = 20, n2 = 20, n_mc = 20, K = 50)