File: calcType1postSelection.R

package info (click to toggle)
r-cran-lavasearch2 2.0.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,832 kB
  • sloc: cpp: 28; sh: 13; makefile: 2
file content (163 lines) | stat: -rw-r--r-- 6,506 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
### calcType1postSelection.R --- 
#----------------------------------------------------------------------
## author: Brice Ozenne
## created: aug 31 2017 (16:42) 
## Version: 
## last-updated: feb  4 2019 (09:40) 
##           By: Brice Ozenne
##     Update #: 130
#----------------------------------------------------------------------
## 
### Commentary: 
## 
### Change Log:
#----------------------------------------------------------------------
## 
### Code:

## * Documentation - calcType1postSelection 
##' @title Compute the Type 1 Error After Selection [EXPERIMENTAL]
##' @description Compute the type 1 error after selection [EXPERIMENTAL].
##' @name calcType1postSelection
##' 
##' @param level [numeric 0-1] expected coverage.
##' @param mu [numeric vector] the expectation of the joint distribution of the test statistics
##' @param Sigma [matrix] the variance-covariance of the joint distribution of the test statistics.
##' @param quantile.previous [numeric] significance quantile used at the previous step.
##' @param df [integer > 0] the degree of freedom of the joint Student's t distribution.
##' Only used when \code{distribution="pvmt"}.
##' @param n [integer > 0] number of points for the numerical integration
##' @param distribution [character] distribution of the test statistics.
##' Can be \code{"pmvnorm"} (normal distribution) or \code{"pvmt"} (Student's t distribution)
##' @param correct [logical] if true, correct the level to account for previous testings.
##' @param ... arguments passed to \code{\link{intDensTri}}.  
##'
##' @details The number of tests at the current step (i.e. after selection) is assumed to be
##' one less than the number of tests at the previous step (i.e. before selection).
##'
##' Arguments \code{mu} and \code{Sigma} must contain the moments for the vector of test statistics
##' before and after selection (in that order).
##' 
##' @return [numeric] the type 1 error.
##' @author Brice Ozenne
##' @examples
##' library(mvtnorm)
##' n <- 350
##' 
##' #### only 2 tests
##' Sigma <- rbind(c(1,0,0),c(0,1,1),c(0,1,1))
##' z2 <- qmvnorm(0.95, mean = rep(0,2), sigma = Sigma[1:2,1:2], tail = "both.tails")$quantile
##' 
##' ## no selection since strong effect
##' mu <- c(10,0,0)
##' calcType1postSelection(0.95, quantile.previous = z2, distribution = "gaussian",
##'                         mu = mu, Sigma = Sigma, correct = TRUE)
##'
##' ## strong selection
##' \dontrun{
##' mu <- c(0,0,0)
##' levelC <- calcType1postSelection(0.95, quantile.previous = z2, distribution = "gaussian",
##'                         mu = mu, Sigma = Sigma)
##' print(levelC) # more liberal than without selection
##' calcType1postSelection(levelC, quantile.previous = z2, distribution = "gaussian",
##'                         mu = mu, Sigma = Sigma, correct = FALSE)
##' }
##'
##' #### 3 tests
##' Sigma <- diag(1,5,5)
##' Sigma[4,2] <- 1
##' Sigma[2,4] <- 1
##' Sigma[5,3] <- 1
##' Sigma[3,5] <- 1
##' 
##' z2 <- qmvnorm(0.95, mean = mu[1:3], sigma = Sigma[1:3,1:3], tails = "both.tails")$quantile
##' 
##' ## no selection since strong effect
##' \dontrun{
##' mu <- c(10,0,0,0,0)
##' calcType1postSelection(0.95, quantile.previous = z2, distribution = "gaussian",
##'                         mu = mu, Sigma = Sigma, correct = TRUE)
##' 
##' ## strong selection
##' mu <- c(0,0,0,0,0)
##' levelC <- calcType1postSelection(0.95, quantile.previous = z2,
##'                         mu = mu, Sigma = Sigma, distribution = "gaussian")
##' calcType1postSelection(levelC, quantile.previous = z2, distribution = "gaussian",
##'                         mu = mu, Sigma = Sigma, correct = FALSE)
##' }
##'
##' @concept post-selection inference


## * calcType1postSelection
##' @rdname calcType1postSelection
##' @export
calcType1postSelection <- function(level, mu, Sigma, quantile.previous, distribution, df,
                                    n = 10, correct = TRUE, ...){

    ## ** normalisation of the arguments
    p <- length(mu)
    if(p %% 2 == 0){
        stop("\'mu\' must have uneven length\n",
             "since it contains the means for the test statistics at the previous step (p+1)/2",
             "and those at the current step (p-1)/2")
    }
    if(NCOL(Sigma)!=p || NROW(Sigma)!=p){
        stop("\'Sigma\' must be a pxp matrix where p is the length of \'mu\' \n")
    }
    nTest <- (p-1)/2
    distribution <- match.arg(distribution, choices = c("student","gaussian"))
    
    if(distribution=="student"){
        pdist <- "pmvt"
        qdist <- "qmvt"
        args.dist <- list(delta = rep(0,nTest),
                          sigma = Sigma[1:nTest,1:nTest,drop=FALSE],
                          tail = "both.tails", df = df)
    }else if(distribution=="gaussian"){
        pdist <- "pmvnorm"
        qdist <- "qmvnorm"
        args.dist <- list(delta = rep(0,nTest),
                          sigma = Sigma[1:nTest,1:nTest,drop=FALSE],
                          tail = "both.tails")
    }    

    ## ** wrapper
    warper <- function(x){ # x <- 0.95## level
        # P[A|B] = 1-P[\bar{A}|B]  = 1-P[\bar{A},B]/P[B]
        ## Current quantile
        args.dist$p <- x
        newQuantile <- do.call(qdist, args = args.dist)$quantile
        
        ## Compute type one error
        num <- intDensTri(mu = mu, Sigma = Sigma, df = df, n=n,
                          x.min = quantile.previous, z.max = rep(newQuantile, nTest),
                          distribution = pdist, ...) # P[\bar{A},B]
        # autoplot(num, coord.plot = c("x","z"))
        denum <- intDensTri(mu = mu[1:(nTest+1)], Sigma = Sigma[1:(nTest+1),1:(nTest+1)], df = df, n=n,
                            x.min = quantile.previous, z.max = NULL,
                            distribution = pdist, ...) # P[B]
        out <- 1-num$value/denum$value
        return(out)
    }

    ## ** compute type1 error
    if(correct){
        out <- stats::optim(par = level, fn = function(x){
            obj <- abs((1-level)-warper(x))
            # cat("level:",x," obj:",obj,"\n")
            return(obj)
        },
        method = "Brent", lower = 0.51, upper = 0.999,
        control = list(abstol = 1e-4, reltol = 1e-4)
        )$par

    }else{
        out <- warper(level)
    }
    
    return(out)
}

#----------------------------------------------------------------------
### calcType1postSelection.R ends here