Skip to content

Commit a861291

Browse files
committed
Removed epitools dependency
1 parent 5b8d7aa commit a861291

File tree

7 files changed

+155
-64
lines changed

7 files changed

+155
-64
lines changed

DESCRIPTION

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: FSA
2-
Version: 0.8.28.9000
3-
Date: 2020-2-28
2+
Version: 0.8.29
3+
Date: 2020-3-8
44
Title: Simple Fisheries Stock Assessment Methods
55
Description: A variety of simple fish stock assessment methods.
66
Detailed vignettes are available on the fishR website <http://derekogle.com/fishR/>.
@@ -26,7 +26,6 @@ Imports:
2626
car,
2727
dplyr,
2828
dunn.test,
29-
epitools,
3029
lmtest,
3130
plotrix,
3231
plyr,

NEWS.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
1-
# FSA 0.8.29 ongoing
1+
# FSA 0.8.29 8-Mar-20
2+
* Removed dependency on `epitools` package as it may soon be orphaned. See changes to `binCI()` and `poiCI()` outlined below.
3+
* `binCI()`: Modified. Added internal functions that are based on (but not identical to) functions in the `epitools` package which will possibly be deprecated soon (per note from CRAN on 7-Mar-20).
4+
* `poiCI()`: Modified. Added internal functions that are based on (but not identical to) functions in the `epitools` package which will possibly be deprecated soon (per note from CRAN on 7-Mar-20).
25

3-
4-
# FSA 0.8.28 28-Feb-18
6+
# FSA 0.8.28 28-Feb-20
57
* `fitPlot()`: Modified. Changed so that lines are plotted after the points in the IVR versions.
68
* `ksTest()`: Modified. Changed documentation examples to handle R's new way of handling `stringsAsFactors=` (per request from CRAN on 27-Feb-20).
79
* `psdAdd()`: Modified. Changed testing to handle R's new way of handling `stringsAsFactors=` (per request from CRAN on 27-Feb-20).
810

911
# FSA 0.8.27 2-Feb-20
10-
* Now using ROxygen2 7.0.2.
12+
* Now using ROxygen2 7.0.2.
1113
* Removed dependency on `gplots` package as it is now orphaned. Required adding `iRichColors()` internal function.
1214
* `lwCompPreds()`: Removed `\dots` from arguments as it was not in usage (per request from CRAN on 3-Feb-20).
1315
* `repeatedRows2Keep()`: Modified. Now makes comparisons as if `NA`s are regular values.

R/CIDists.R

Lines changed: 110 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@
2222
#'
2323
#' @return A #x2 matrix that contains the lower and upper confidence interval bounds as columns and, if \code{verbose=TRUE} \code{x}, \code{n}, and \code{x/n} .
2424
#'
25-
#' @author Derek H. Ogle, \email{derek@@derekogle.com}
25+
#' @author Derek H. Ogle, \email{derek@@derekogle.com}, though this is largely based on \code{binom.exact}, \code{binom.wilson}, and \code{binom.approx} from the old epitools package.
2626
#'
27-
#' @seealso See \code{\link{binom.test}}; \code{binconf} in \pkg{Hmisc}; \code{binom.exact}, \code{binom.wilson}, and \code{binom.approx} documented in \code{\link[epitools]{binom.conf.int}} in \pkg{epitools}, and functions in \pkg{binom}.
27+
#' @seealso See \code{\link{binom.test}}; \code{binconf} in \pkg{Hmisc}; and functions in \pkg{binom}.
2828
#'
2929
#' @references Agresti, A. and B.A. Coull. 1998. Approximate is better than \dQuote{exact} for interval estimation of binomial proportions. American Statistician, 52:119-126.
3030
#'
@@ -51,6 +51,33 @@
5151
#' @export
5252
binCI <- function(x,n,conf.level=0.95,type=c("wilson","exact","asymptotic"),
5353
verbose=FALSE) {
54+
## Internal functions ... largely but not exactly from old epitools
55+
iBinWilson <- function(x,n,conf.level) {
56+
Z <- stats::qnorm(1-(1-conf.level)/2)
57+
Z1 <- Z*sqrt(((x*(n-x))/n^3)+Z^2/(4*n^2))
58+
lwr <- (n/(n+Z^2))*(x/n+Z^2/(2*n)-Z1)
59+
upr <- (n/(n+Z^2))*(x/n+Z^2/(2*n)+Z1)
60+
res <- cbind(x,n,x/n,lwr,upr)
61+
colnames(res) <- c("x","n","proportion",iCILabel(conf.level))
62+
res
63+
}
64+
iBinExact <- function(x,n,conf.level) {
65+
tmp <- apply(cbind(x,n-x),MARGIN=1,FUN=stats::binom.test,
66+
conf.level=conf.level)
67+
tmp <- t(sapply(tmp,"[[","conf.int"))
68+
res <- cbind(x,n,x/n,tmp)
69+
colnames(res) <- c("x","n","proportion",iCILabel(conf.level))
70+
res
71+
}
72+
iBinAsymp <- function(x,n,conf.level) {
73+
Z <- stats::qnorm(1-(1-conf.level)/2)
74+
SE <- sqrt(x*(n-x)/(n^3))
75+
res <- cbind(x,n,x/n,x/n-Z*SE,x/n+Z*SE)
76+
colnames(res) <- c("x","n","proportion",iCILabel(conf.level))
77+
res
78+
}
79+
80+
## Checks
5481
type <- match.arg(type,several.ok=TRUE)
5582
if (!is.vector(x)) STOP("'x' must be a single or vector of whole numbers.")
5683
if (!is.vector(n)) STOP("'n' must be a single or vector of whole numbers.")
@@ -62,28 +89,28 @@ binCI <- function(x,n,conf.level=0.95,type=c("wilson","exact","asymptotic"),
6289
if (any(n<0)) STOP("'n' must be non-negative.")
6390
if (any(x>n)) STOP("'x' must not be greater than 'n'.")
6491
if (conf.level<=0 | conf.level>=1) STOP("'conf.level' must be between 0 and 1.")
65-
## Handle differently depending on number of xs given
92+
93+
## Process
94+
### Handle differently depending on number of xs given
6695
if (length(x)>1) {
6796
if (length(type)>1) {
6897
type <- type[1]
6998
WARN("Can't use multiple 'type's with multiple 'x's. Used only '",type,"'.")
7099
}
71100
switch(type,
72-
exact = { res <- epitools::binom.exact(x,n,conf.level) },
73-
wilson = { res <- epitools::binom.wilson(x,n,conf.level) },
74-
asymptotic = { res <- epitools::binom.approx(x,n,conf.level) })
101+
exact = { res <- iBinExact(x,n,conf.level) },
102+
wilson = { res <- iBinWilson(x,n,conf.level) },
103+
asymptotic = { res <- iBinAsymp(x,n,conf.level) })
75104
} else {
76-
res <- rbind(epitools::binom.exact(x,n,conf.level),
77-
epitools::binom.wilson(x,n,conf.level),
78-
epitools::binom.approx(x,n,conf.level))
105+
res <- rbind(iBinExact(x,n,conf.level),
106+
iBinWilson(x,n,conf.level),
107+
iBinAsymp(x,n,conf.level))
79108
rownames(res) <- c("Exact","Wilson","Asymptotic")
80109
# reduce to selected types
81-
res <- res[rownames(res) %in% capFirst(type),]
110+
res <- res[rownames(res) %in% capFirst(type),,drop=FALSE]
82111
}
83-
# relabel CI columns, convert to matrix, drop unwanted columns
84-
names(res)[which(names(res) %in% c("lower","upper"))] <- iCILabel(conf.level)
85-
res <- as.matrix(res[,-6])
86-
# return everything if verbose=TRUE, otherwise just CI
112+
113+
### return everything if verbose=TRUE, otherwise just CI
87114
if (!verbose) {
88115
res <- res[,4:5,drop=FALSE]
89116
# remove rownname if only one type selected and not verbose
@@ -100,7 +127,9 @@ binCI <- function(x,n,conf.level=0.95,type=c("wilson","exact","asymptotic"),
100127
#'
101128
#' @description Computes a confidence interval for the Poisson counts.
102129
#'
103-
#' @details Computes a CI for the Poisson counts using the \code{exact}, gamma distribution (\code{daly}`), Byar's (\code{byar}), or normal approximation (\code{asymptotic}) methods. This is largely a wrapper to \code{pois.exact}, \code{pois.daly}, \code{pois.byar}, and \code{pois.approx} functions documented in \code{\link[epitools]{pois.conf.int}}in \pkg{epitools}.
130+
#' @details Computes a CI for the Poisson counts using the \code{exact}, gamma distribution (\code{daly}`), Byar's (\code{byar}), or normal approximation (\code{asymptotic}) methods.
131+
#'
132+
#' The \code{pois.daly} function gives essentially identical answers to the \code{pois.exact} function except when x=0. When x=0, for the upper confidence limit \code{pois.exact} returns 3.689 and \code{pois.daly} returns 2.996.
104133
#'
105134
#' @param x A single number or vector that represents the number of observed successes.
106135
#' @param conf.level A number that indicates the level of confidence to use for constructing confidence intervals (default is \code{0.95}).
@@ -109,9 +138,7 @@ binCI <- function(x,n,conf.level=0.95,type=c("wilson","exact","asymptotic"),
109138
#'
110139
#' @return A #x2 matrix that contains the lower and upper confidence interval bounds as columns and, if \code{verbose=TRUE} \code{x}.
111140
#'
112-
#' @author Derek H. Ogle, \email{derek@@derekogle.com}
113-
#'
114-
#' @seealso See \code{pois.exact}, \code{pois.daly}, \code{pois.byar}, and \code{pois.approx} (documented in \code{\link[epitools]{pois.conf.int}}) in \pkg{epitools} for more description and references.
141+
#' @author Derek H. Ogle, \email{derek@@derekogle.com}, though this is largely based on \code{pois.exact}, \code{pois.daly}, \code{pois.byar}, and \code{pois.approx} from the old epitools package.
115142
#'
116143
#' @keywords htest
117144
#'
@@ -134,36 +161,87 @@ binCI <- function(x,n,conf.level=0.95,type=c("wilson","exact","asymptotic"),
134161
#' @export
135162
poiCI <- function(x,conf.level=0.95,type=c("exact","daly","byar","asymptotic"),
136163
verbose=FALSE) {
164+
## Internal Functions ... largely but not exactly from old epitools
165+
iPoiExact <- function(x,conf.level) {
166+
f1 <- function(x,ans,alpha=1-conf.level) stats::ppois(x,ans)-alpha/2
167+
f2 <- function(x,ans,alpha=1-conf.level)
168+
1-stats::ppois(x,ans)+stats::dpois(x,ans)-alpha/2
169+
res <- matrix(NA,nrow=length(x),3)
170+
for(i in 1:length(x)){
171+
interval <- c(0,x[i]*5+4)
172+
uci <- stats::uniroot(f1,interval=interval,x=x[i])$root
173+
if(x[i]==0) lci <- 0
174+
else lci <- stats::uniroot(f2,interval=interval,x=x[i])$root
175+
res[i,] <- c(x[i],lci,uci)
176+
}
177+
colnames(res) <- c("x",iCILabel(conf.level))
178+
res
179+
}
180+
iPoiDaly <- function(x,conf.level) {
181+
iDalyCI <- function(x,conf.level){
182+
if(x!=0){
183+
LL <- stats::qgamma((1-conf.level)/2,x)
184+
UL <- stats::qgamma((1+conf.level)/2,x+1)
185+
} else {
186+
if(x==0){
187+
LL <- 0
188+
UL <- -log(1-conf.level)
189+
}
190+
}
191+
cbind(x=x,lower=LL,upper=UL)
192+
}
193+
res <- t(apply(matrix(x,ncol=1),MARGIN=1,FUN=iDalyCI,conf.level=conf.level))
194+
colnames(res) <- c("x",iCILabel(conf.level))
195+
res
196+
}
197+
iPoiByar <- function(x,conf.level) {
198+
Z <- stats::qnorm(1-(1-conf.level)/2)
199+
aprime <- x+0.5
200+
Z1 <- (Z/3)*sqrt(1/aprime)
201+
lwr <- (aprime*(1-1/(9*aprime)-Z1)^3)
202+
upr <- (aprime*(1-1/(9*aprime)+Z1)^3)
203+
res <- cbind(x,lwr,upr)
204+
colnames(res) <- c("x",iCILabel(conf.level))
205+
res
206+
}
207+
iPoiAsymp <- function(x,conf.level) {
208+
Z <- stats::qnorm(1-(1-conf.level)/2)
209+
res <- cbind(x,x-Z*sqrt(x),x+Z*sqrt(x))
210+
colnames(res) <- c("x",iCILabel(conf.level))
211+
res
212+
}
213+
214+
## Checks
137215
type <- match.arg(type,several.ok=TRUE)
138216
if (!is.vector(x)) STOP("'x' must be a single or vector of whole numbers.")
139217
if (!is.numeric(x)) STOP("'x' must be a whole number.")
140218
if (!all(is.wholenumber(x))) STOP("'x' must be a whole number.")
141219
if (any(x<0)) STOP("'x' must be non-negative.")
142220
if (conf.level<=0 | conf.level>=1) STOP("'conf.level' must be between 0 and 1.")
143-
## Handle differently depending on number of xs given
221+
222+
## Process
223+
### Handle differently depending on number of xs given
144224
if (length(x)>1) {
145225
if (length(type)>1) {
146226
type <- type[1]
147227
WARN("Can't use multiple 'type's with multiple 'x's. Used only '",type,"'.")
148228
}
149229
switch(type,
150-
exact = { res <- epitools::pois.exact(x,1,conf.level) },
151-
daly = { res <- epitools::pois.daly(x,1,conf.level) },
152-
byar = { res <- epitools::pois.byar(x,1,conf.level) },
153-
asymptotic = { res <- epitools::pois.approx(x,1,conf.level) })
230+
exact = { res <- iPoiExact(x,conf.level) },
231+
daly = { res <- iPoiDaly(x,conf.level) },
232+
byar = { res <- iPoiByar(x,conf.level) },
233+
asymptotic = { res <- iPoiAsymp(x,conf.level) })
154234
} else {
155-
res <- rbind(epitools::pois.exact(x,1,conf.level),
156-
epitools::pois.daly(x,1,conf.level),
157-
epitools::pois.byar(x,1,conf.level),
158-
epitools::pois.approx(x,1,conf.level))
235+
res <- rbind(iPoiExact(x,conf.level),
236+
iPoiDaly(x,conf.level),
237+
iPoiByar(x,conf.level),
238+
iPoiAsymp(x,conf.level))
159239
rownames(res) <- c("Exact","Daly","Byar","Asymptotic")
160240
# reduce to selected types
161-
res <- res[rownames(res) %in% capFirst(type),]
241+
res <- res[rownames(res) %in% capFirst(type),,drop=FALSE]
162242
}
163-
# relabel CI columns, convert to matrix, drop unwanted columns
164-
names(res)[which(names(res) %in% c("lower","upper"))] <- iCILabel(conf.level)
165-
res <- as.matrix(res[,-c(2,3,6)])
166-
# return everything if verbose=TRUE, otherwise just CI
243+
244+
### return everything if verbose=TRUE, otherwise just CI
167245
if (!verbose) {
168246
res <- res[,2:3,drop=FALSE]
169247
# remove rownname if only one type selected and not verbose

inst/helpers/installTester.R

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ tmp <- filterD(df,y<10)
1818
## test of dunn.test functions
1919
dunnTest(y~f,data=df)
2020

21-
## test of epitools functions
22-
binCI(7,20)
23-
poiCI(12)
24-
2521
## test of lmtest functions
2622
lrt(slrout,com=ivrout)
2723

@@ -52,7 +48,6 @@ library(plyr)
5248
library(dplyr)
5349
library(car)
5450
library(dunn.test)
55-
library(epitools)
5651
library(lmtest)
5752
library(plotrix)
5853
library(sciplot)

man/binCI.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/poiCI.Rd

Lines changed: 4 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/testthat_ciDists.R

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -210,29 +210,47 @@ test_that("poiCI() output types",{
210210

211211
## Validate Results ----
212212
test_that("binCI() compared to epitools functions",{
213-
res <- as.data.frame(binCI(7,10,verbose=TRUE))
214-
resepi <- rbind(epitools::binom.exact(7,10),
215-
epitools::binom.wilson(7,10),
216-
epitools::binom.approx(7,10))[,-6]
213+
res <- binCI(7,10,verbose=TRUE)
214+
res[,4:5] <- round(res[,4:5],7)
215+
### These are hand-entered results from old epitools package
216+
resepi <- matrix(c(7,10,0.7,0.3475471,0.9332605,
217+
7,10,0.7,0.3967781,0.8922087,
218+
7,10,0.7,0.4159742,0.9840258),nrow=3,byrow=TRUE)
217219
rownames(resepi) <- c("Exact","Wilson","Asymptotic")
220+
colnames(resepi) <- c("x","n","proportion","lower","upper")
218221
expect_equivalent(res,resepi)
219222

220-
res <- as.data.frame(binCI(5:7,10,type="wilson",verbose=TRUE))
221-
resepi <- epitools::binom.wilson(5:7,10)[,-6]
223+
res <- binCI(5:7,10,type="wilson",verbose=TRUE)
224+
res[,4:5] <- round(res[,4:5],7)
225+
### These are hand-entered results from old epitools package
226+
resepi <- matrix(c(5,10,0.5,0.2365931,0.7634069,
227+
6,10,0.6,0.3126738,0.8318197,
228+
7,10,0.7,0.3967781,0.8922087),nrow=3,byrow=TRUE)
229+
colnames(resepi) <- c("x","n","proportion","lower","upper")
222230
expect_equivalent(res,resepi)
223231
})
224232

225233
test_that("poiCI() compared to epitools functions",{
226-
res <- as.data.frame(poiCI(10,verbose=TRUE))
227-
resepi <- rbind(epitools::pois.exact(10),
228-
epitools::pois.daly(10),
229-
epitools::pois.byar(10),
230-
epitools::pois.approx(10))[,-c(2,3,6)]
234+
res <- poiCI(10,verbose=TRUE)
235+
res[,2] <- round(res[,2],6)
236+
res[,3] <- round(res[,3],5)
237+
### These are hand-entered results from old epitools package
238+
resepi <- matrix(c(10,4.795389,18.39036,
239+
10,4.795389,18.39036,
240+
10,5.133753,17.74048,
241+
10,3.802050,16.19795),nrow=4,byrow=TRUE)
231242
rownames(resepi) <- c("Exact","Daly","Byar","Asymptotic")
243+
colnames(resepi) <- c("x","lower","upper")
232244
expect_equivalent(res,resepi)
233245

234-
res <- as.data.frame(poiCI(5:7,type="exact",verbose=TRUE))
235-
resepi <- epitools::pois.exact(5:7)[,-c(2,3,6)]
246+
res <- poiCI(5:7,type="exact",verbose=TRUE)
247+
res[,2] <- round(res[,2],6)
248+
res[,3] <- round(res[,3],5)
249+
### These are hand-entered results from old epitools package
250+
resepi <- matrix(c(5,1.623486,11.66832,
251+
6,2.201891,13.05948,
252+
7,2.814358,14.42268),nrow=3,byrow=TRUE)
253+
colnames(resepi) <- c("x","lower","upper")
236254
expect_equivalent(res,resepi)
237255
})
238256

0 commit comments

Comments
 (0)