Skip to content

Commit f9654f8

Browse files
Ting Fung (Ralph) Macran-robot
Ting Fung (Ralph) Ma
authored andcommitted
version 0.4.0
0 parents  commit f9654f8

19 files changed

+1019
-0
lines changed

DESCRIPTION

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Package: FertBoot
2+
Type: Package
3+
Title: Fertilizer Response Curve Analysis by Bootstrapping Residuals
4+
Version: 0.4.0
5+
Authors@R: c(person("Ting Fung (Ralph)", "Ma", email = "[email protected]", role = c("cre", "aut")),
6+
person("Hannah", "Francis", email = "[email protected]", role = "aut"),
7+
person("Matt", "Ruark", role = "ctb"))
8+
Maintainer: Ting Fung (Ralph) Ma <[email protected]>
9+
Description: Quantify variability (such as confidence interval) of fertilizer response curves and optimum fertilizer rates using bootstrapping residuals with several popular non-linear and linear models.
10+
Imports: stats, nls.multstart, simpleboot
11+
License: GPL-2
12+
Encoding: UTF-8
13+
LazyData: true
14+
RoxygenNote: 7.0.2
15+
NeedsCompilation: no
16+
Packaged: 2020-07-14 17:17:17 UTC; Ralph
17+
Author: Ting Fung (Ralph) Ma [cre, aut],
18+
Hannah Francis [aut],
19+
Matt Ruark [ctb]
20+
Repository: CRAN
21+
Date/Publication: 2020-07-18 09:32:17 UTC

MD5

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
cf46442d80c8f64d5c98d450cabd65e6 *DESCRIPTION
2+
c90f950aef0038c9f28f95b0278153a3 *NAMESPACE
3+
e51d94089628154d5b91a780fb362c08 *R/boot.CI.R
4+
a790ca6b477fa3eac45312dc1f910acc *R/boot.resid.linear.plateau.R
5+
ad128e3018f4614f772f1ab873582fb3 *R/boot.resid.quad..R
6+
27a49d0e3aea09e667e574d8354cbcae *R/boot.resid.quad.plateau.R
7+
afc7548a77a84882e90c54b9da65300c *R/compare.two.sample.R
8+
78200e1f92ae26d08ad46c594e994c2f *R/f.linear.plateau.R
9+
f812fc47d9a078d5931d3705b546f82f *R/f.quad.R
10+
f29ad8c1d0c22cdc0f802389f6a5547d *R/f.quad.plateau.R
11+
c8b1617d446d92b00279b22588aa4ec9 *man/boot.CI.Rd
12+
2c303a1c98a115a3dbc6dd6ea76464d0 *man/boot.resid.linear.plateau.Rd
13+
bf0f9c3c8e610bbc5ab8cc9f114ed0b2 *man/boot.resid.quad.Rd
14+
0b6da7c23d44131a62073514cb0d5ecf *man/boot.resid.quad.plateau.Rd
15+
4674a98de8082bf9e84e8bcaea26e91a *man/compare.two.sample.Rd
16+
c289928245408a5784a745e3527c7607 *man/f.linear.plateau.Rd
17+
894f7c8610174e917ca7cf9f209be6f6 *man/f.quad.Rd
18+
25e15a97f7e2873c5acc1115a4b50607 *man/f.quad.plateau.Rd

NAMESPACE

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Generated by roxygen2: do not edit by hand
2+
3+
export(boot.CI)
4+
export(boot.resid.linear.plateau)
5+
export(boot.resid.quad)
6+
export(boot.resid.quad.plateau)
7+
export(compare.two.sample)
8+
export(f.linear.plateau)
9+
export(f.quad)
10+
export(f.quad.plateau)
11+
import(nls.multstart)
12+
import(simpleboot)
13+
import(stats)

R/boot.CI.R

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#' Bootstrap confidence intervals of mean
2+
#' @param x a vector of observation
3+
#' @param alpha significance level (default: 0.05)
4+
#' @param CI.type type of CI required (default: "all")
5+
#'
6+
#' @return \code{boot.CI} return list of confidence intervals of mean (\code{CI.percent}: percentile, \code{CI.BC}:bias-corrected and \code{CI.BCa}: bias-corrected and accelerated)
7+
#' @import stats nls.multstart simpleboot
8+
#' @examples
9+
#'
10+
#' set.seed(12)
11+
#' boot.CI(rnorm(1000, mean=0, sd=1), alpha=0.05, CI.type="per") # example of wrong input for type
12+
#' boot.CI(rnorm(1000, mean=0, sd=1), alpha=0.05, CI.type="all") # require all type
13+
#'
14+
#' @export
15+
#'
16+
boot.CI <- function(x, alpha=0.05, CI.type="all") {
17+
B <- length(x)
18+
19+
result <- NULL
20+
21+
if ("percentile" %in% CI.type || "all" %in% CI.type) {
22+
# Percentile CI
23+
CI.percent <- quantile(x, c(alpha/2, 1 - alpha/2))
24+
25+
result <- c(result, list(CI.percent=CI.percent))
26+
}
27+
28+
29+
if ("BC" %in% CI.type || "all" %in% CI.type) {
30+
# Bias-corrected CI
31+
z0 <- qnorm(sum(x < mean(x))/B)
32+
CI.BC <- quantile(x, c(pnorm(qnorm(alpha/2) + 2*z0), pnorm(qnorm(1-alpha/2) + 2*z0)))
33+
34+
result <- c(result, list(CI.BC=CI.BC))
35+
}
36+
37+
if ("BCa" %in% CI.type || "all" %in% CI.type) {
38+
# Accelerated bias-corrected CI
39+
theta <- rep(NA, B)
40+
for (i in 1:B) {theta[i] <- mean(x[-i])}
41+
theta.mean <- mean(theta)
42+
43+
a <- sum((theta.mean - theta)^3)/(6*sum((theta.mean - theta)^2)^1.5)
44+
45+
alpha1 <- pnorm(z0 + (z0 + qnorm(alpha/2))/(1-a*(z0 + qnorm(alpha/2))))
46+
alpha2 <- pnorm(z0 + (z0 + qnorm(1 - alpha/2))/(1-a*(z0 + qnorm(1 - alpha/2))))
47+
CI.BCa <- quantile(x, c(alpha1, alpha2))
48+
49+
result <- c(result, list(CI.BCa=CI.BCa))
50+
}
51+
52+
if (is.null(result)) {
53+
cat("Auto-corrected with percentile CI!\n")
54+
result <- boot.CI(x, alpha=0.05, CI.type="percentile")
55+
}
56+
57+
result
58+
}

R/boot.resid.linear.plateau.R

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#' Linear plateau model estimation by bootstrapping residuals
2+
#'
3+
#' \code{boot.resid.linear.plateau} is the core function that implement bootstrapping residuals on quadratic plateau model, which assumes
4+
#' y ~ a + b * (x - c) * (x <= c). Note that this functions may take minutes up to days. Parallel computing could be considered when necessary. We suggest users start with a smaller \code{B} and moderate \code{n.start} to see if the bootstrap models can convergence. In general, increasing \code{n.start} and \code{plus_minus} may help convergence. For rigorous statistical inference, \code{B} should be reach order of thousand.
5+
#'
6+
#'
7+
#' @param mod a full model list, probably from \code{f.linear.plateau()}
8+
#' @param data data drame with two columns (\code{x} and \code{y})
9+
#' @param x.range vector of data.frame with one column for range of N rate of interested for prediction interval
10+
#' @param B bootstrap sample size
11+
#' @param plus_minus radius of random initial values (default: \code{100})
12+
#' @param n.start total number of initial points considered (deafult: \code{1000})
13+
#' @param print.progress logical flag whehter printing progress
14+
#'
15+
#' @return \code{boot.resid.linear.plateau} returns a list of two elements:
16+
#' \code{result}: matrix with B rows and columns containing bootstrap sample for parameter (\code{a,b,c}), optimal N and yield (\code{max_x, max_y}), log-likelihood (\code{logLik}) and N values of interest;
17+
#' \code{x.range}: range of x considered for prediction interval (same as \code{x.range} in vector form)
18+
#'
19+
#' @import stats nls.multstart simpleboot
20+
#'
21+
#' @examples
22+
#'
23+
#'\donttest{
24+
#' set.seed(1)
25+
#' x <- rep(1:300, each=4)
26+
#' a <- 8; b <- 0.05; c <- 100
27+
#' y <- a + b * (x - c) * (x <= c) +
28+
#' rnorm(length(x), sd=1)
29+
#' d <- cbind(x,y)
30+
#'
31+
#' # a converged example:
32+
#' ans <- f.linear.plateau(d, start=list(a = 7, b = 0.1, c = 150),
33+
#' plus_minus=10, n.start=10, msg=FALSE)
34+
#'
35+
#'
36+
#' ans.boot <- boot.resid.linear.plateau(ans, d, x.range=seq(0,280,by=40),
37+
#' B=99, plus_minus = 1e2, n.start=1000, print.progress=TRUE)
38+
#'
39+
#' }
40+
#'
41+
#'
42+
#'
43+
#' @export
44+
#'
45+
boot.resid.linear.plateau <- function(mod, data, x.range=data.frame(x=seq(0,280,by=40)), B=1e2-1, plus_minus = 1e2, n.start=5000, print.progress=TRUE) {
46+
47+
if (class(x.range) == "numeric") x.range <- data.frame(x=x.range)
48+
49+
# a, b, c, max x value, max y value, logLik
50+
result <- data.frame(matrix(NA, nrow= B + 1, ncol=6 + NROW(x.range)))
51+
names(result) <- c("a", "b", "c", "max_x", "max_y", "logLik", paste0("x_", x.range[,1]))
52+
53+
data <- data.frame(data)
54+
55+
data.tmp <- data ; names(data.tmp) <- c("x", "y")
56+
57+
58+
fit.value <- fitted(mod$nls.model)
59+
res.value <- residuals(mod$nls.model)
60+
start.value <- list(a=coef(mod$nls.model)[1], b=coef(mod$nls.model)[2], c=coef(mod$nls.model)[3])
61+
62+
result[1, ] <- c(mod$nls.summary[c(1:3,10,9),], logLik(mod$nls.model),
63+
predict(mod$nls.model, newdata=x.range))
64+
i <- 1
65+
while (i <= B) {
66+
if (print.progress) cat("Bootstrap residuals:", i,"out of",B,"\n")
67+
68+
# Bootstrap residual
69+
data.tmp$y <- as.numeric(fit.value + sample(res.value, replace=TRUE))
70+
71+
m.tmp <- f.linear.plateau(d=data.tmp, start=start.value, plus_minus=plus_minus, n.start=n.start)
72+
73+
if(!is.null(m.tmp$nls.model)) {
74+
result[i+1, ] <- c(m.tmp$nls.summary[c(1:3,10,9),], logLik(m.tmp$nls.model),
75+
predict(m.tmp$nls.model, newdata=x.range))
76+
i <- i + 1
77+
}else{ if (print.progress) cat("Not converged! Retry...\n")}
78+
}
79+
list(result=result, x.range = x.range[,1])
80+
}
81+

R/boot.resid.quad..R

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#' Fitting quadratic plateau model using mutiple initial vaues
2+
#'
3+
#' \code{boot.resid.quad.plateau} is the core function that implement bootstrapping residuals on quadratic plateau model, which assumes
4+
#' y = (a + b * x + c *x^2) * (x <= -0.5*b/c) + (a + -b^2/(4 * c)) * (x > -0.5 * b/c). Note that this functions may take minutes up to days. Parallel computing could be considered when necessary. We suggest users start with a smaller \code{B} and moderate \code{n.start} to see if the bootstrap models can convergence. In general, increasing \code{n.start} and \code{plus_minus} may help convergence. For rigorous statistical inference, \code{B} should be reach order of thousand.
5+
#'
6+
#'
7+
#' @param mod a full model list, probably from \code{f.quad.plateau()}
8+
#' @param data data drame with two columns (\code{x} and \code{y})
9+
#' @param x.range vector of data.frame with one column for range of N rate of interested for prediction interval
10+
#' @param B bootstrap sample size
11+
#' @param plus_minus radius of random initial values (default: \code{100})
12+
#' @param n.start total number of initial points considered (deafult: \code{1000})
13+
#' @param print.progress logical flag whehter printing progress
14+
#'
15+
#' @return \code{boot.resid.quad.plateau} returns a list of two elements:
16+
#' \code{result}: matrix with B rows and columns containing bootstrap sample for parameter (\code{a,b,c}), optimal N and yield (\code{max_x, max_y}), log-likelihood (\code{logLik}) and N values of interest;
17+
#' \code{x.range}: range of x considered for prediction interval (same as \code{x.range} in vector form)
18+
#'
19+
#' @import stats nls.multstart simpleboot
20+
#'
21+
#' @examples
22+
#'
23+
#' \donttest{
24+
#'
25+
#' set.seed(1)
26+
#' x <- rep(1:300, each=5)
27+
#' a <- 8; b <- 0.05; c <- -1e-3
28+
#' y <- (a + b * x + c *x^2) * (x <= -0.5*b/c) + (a + -b^2/(4 * c)) * (x > -0.5 * b/c) +
29+
#' rnorm(length(x), sd=0.1)
30+
#' d <- cbind(x,y)
31+
#'
32+
#' ans <- f.quad.plateau(d, start=list(a = 7, b = 0.02, c = 1e-5),
33+
#' plus_minus=10, n.start=10, msg=FALSE)
34+
#'
35+
#'
36+
#' ans.boot <- boot.resid.quad.plateau(ans, d, x.range=seq(0,280,by=40),
37+
#' B=1e1, plus_minus = 1e2, n.start=1e3, print.progress=TRUE)
38+
#'
39+
#' }
40+
#'
41+
#'
42+
#'
43+
#' @export
44+
#'
45+
boot.resid.quad <- function(mod, data, x.range=data.frame(x=seq(0,280,by=40)),
46+
B=1e2-1, plus_minus = 1e1, n.start=20, print.progress=TRUE) {
47+
48+
if (class(x.range) == "numeric") x.range <- data.frame(x=x.range)
49+
50+
# a, b, c, max x value, max y value, logLik
51+
result <- data.frame(matrix(NA, nrow= B + 1, ncol=6 + NROW(x.range)))
52+
names(result) <- c("a", "b", "c", "max_x", "max_y", "logLik", paste0("x_", x.range[,1]))
53+
54+
data.tmp <- data ; names(data.tmp) <- c("x", "y")
55+
56+
57+
58+
fit.value <- fitted(mod$nls.model)
59+
res.value <- residuals(mod$nls.model)
60+
start.value <- list(a=coef(mod$nls.model)[1], b=coef(mod$nls.model)[2], c=coef(mod$nls.model)[3])
61+
62+
result[1, ] <- c(mod$nls.summary[c(1:3,10,9),], logLik(mod$nls.model),
63+
predict(mod$nls.model, newdata=x.range))
64+
i <- 1
65+
while (i <= B) {
66+
if (print.progress) cat("Bootstrap residuals:", i,"out of",B,"\n")
67+
68+
# Bootstrap residual
69+
data.tmp$y <- as.numeric(fit.value + sample(res.value, replace=TRUE))
70+
71+
m.tmp <- f.quad(d=data.tmp, start=start.value, plus_minus=plus_minus, n.start=n.start)
72+
73+
if(!is.null(m.tmp$nls.model)) {
74+
75+
result[i+1, ] <- c(m.tmp$nls.summary[c(1:3,10,9),], logLik(m.tmp$nls.model),
76+
predict(m.tmp$nls.model, newdata=x.range))
77+
i <- i + 1
78+
}else{ if (print.progress) cat("Not converged! Retry...\n")}
79+
}
80+
list(result=result, x.range=x.range[,1])
81+
}
82+

R/boot.resid.quad.plateau.R

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#' Quadratic plateau model estimation by bootstrapping residuals
2+
#'
3+
#' \code{boot.resid.quad.plateau} is the core function that implement bootstrapping residuals on quadratic plateau model, which assumes
4+
#' y = (a + b * x + c *x^2) * (x <= -0.5*b/c) + (a + -b^2/(4 * c)) * (x > -0.5 * b/c). Note that this functions may take minutes up to days. Parallel computing could be considered when necessary. We suggest users start with a smaller \code{B} and moderate \code{n.start} to see if the bootstrap models can convergence. In general, increasing \code{n.start} and \code{plus_minus} may help convergence. For rigorous statistical inference, \code{B} should be reach order of thousand.
5+
#'
6+
#'
7+
#' @param mod a full model list, probably from \code{f.quad.plateau()}
8+
#' @param data data drame with two columns (\code{x} and \code{y})
9+
#' @param x.range vector of data.frame with one column for range of N rate of interested for prediction interval
10+
#' @param B bootstrap sample size
11+
#' @param plus_minus radius of random initial values (default: \code{100})
12+
#' @param n.start total number of initial points considered (deafult: \code{1000})
13+
#' @param print.progress logical flag whehter printing progress
14+
#'
15+
#' @return \code{boot.resid.quad.plateau} returns a list of two elements:
16+
#' \code{result}: matrix with B rows and columns containing bootstrap sample for parameter (\code{a,b,c}), optimal N and yield (\code{max_x, max_y}), log-likelihood (\code{logLik}) and N values of interest;
17+
#' \code{x.range}: range of x considered for prediction interval (same as \code{x.range} in vector form)
18+
#'
19+
#' @import stats nls.multstart simpleboot
20+
#'
21+
#' @examples
22+
#'
23+
#'\donttest{
24+
#' set.seed(1)
25+
#' x <- rep(1:300, each=5)
26+
#' a <- 8; b <- 0.05; c <- -1e-4
27+
#' y <- (a + b * x + c *x^2) * (x <= -0.5*b/c) + (a + -b^2/(4 * c)) * (x > -0.5 * b/c) +
28+
#' rnorm(length(x), sd=0.1)
29+
#' d <- cbind(x,y)
30+
#'
31+
#' ans <- f.quad.plateau(d, start=list(a = 7, b = 0.02, c = 1e-5),
32+
#' plus_minus=10, n.start=10, msg=FALSE)
33+
#'
34+
#'
35+
#' boot.resid.quad.plateau(ans, d, x.range=seq(0,280,by=40),
36+
#' B=1e2-1, plus_minus = 1e2, n.start=1000, print.progress=TRUE)
37+
#'
38+
#' }
39+
#'
40+
#'
41+
#'
42+
#' @export
43+
#'
44+
boot.resid.quad.plateau <- function(mod, data, x.range=data.frame(x=seq(0,280,by=40)), B=1e2-1, plus_minus = 1e2, n.start=5000, print.progress=TRUE) {
45+
46+
if (class(x.range) == "numeric") x.range <- data.frame(x=x.range)
47+
48+
# a, b, c, max x value, max y value, logLik
49+
result <- data.frame(matrix(NA, nrow= B + 1, ncol=6 + NROW(x.range)))
50+
names(result) <- c("a", "b", "c", "max_x", "max_y", "logLik", paste0("x_", x.range[,1]))
51+
52+
data <- data.frame(data)
53+
54+
data.tmp <- data ; names(data.tmp) <- c("x", "y")
55+
56+
57+
fit.value <- fitted(mod$nls.model)
58+
res.value <- residuals(mod$nls.model)
59+
start.value <- list(a=coef(mod$nls.model)[1], b=coef(mod$nls.model)[2], c=coef(mod$nls.model)[3])
60+
61+
result[1, ] <- c(mod$nls.summary[c(1:3,10,9),], logLik(mod$nls.model),
62+
predict(mod$nls.model, newdata=x.range))
63+
i <- 1
64+
while (i <= B) {
65+
if (print.progress) cat("Bootstrap residuals:", i,"out of",B,"\n")
66+
67+
# Bootstrap residual
68+
data.tmp$y <- as.numeric(fit.value + sample(res.value, replace=TRUE))
69+
70+
m.tmp <- f.quad.plateau(d=data.tmp, start=start.value, plus_minus=plus_minus, n.start=n.start)
71+
72+
if(!is.null(m.tmp$nls.model)) {
73+
result[i+1, ] <- c(m.tmp$nls.summary[c(1:3,10,9),], logLik(m.tmp$nls.model),
74+
predict(m.tmp$nls.model, newdata=x.range))
75+
i <- i + 1
76+
}else{ if (print.progress) cat("Not converged! Retry...\n")}
77+
}
78+
list(result=result, x.range = x.range[,1])
79+
}
80+

R/compare.two.sample.R

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#' Two sample bootstrap test for comparing different in \code{sample1} and \code{sample2}, not necessary with same sample size
2+
#' @param sample1 first sample
3+
#' @param sample2 second sample
4+
#' @param fun statistic (univariate) to be compared (default: \code{mean})
5+
#' @param R number of resample (deafult: \code{1000})
6+
#' @return \code{compare.two.sample} return a list with two components, namely,
7+
#' \code{p.value}: two tailed p-value for the bootstrap test
8+
#' \code{object}: a "\code{simpleboot}" object allowing further analysis using other R packages, such as \code{boot})
9+
#'
10+
#' @import stats nls.multstart simpleboot
11+
#' @examples
12+
#'
13+
#' set.seed(1203)
14+
#' # compare median of two expontential r.v.
15+
#' compare.two.sample(rexp(100, rate=1), rexp(100, rate=2), fun=median, R=1e3)$p.value
16+
#'
17+
#' f.Q1 <- function(x) quantile(x, probs=0.25)
18+
#' compare.two.sample(rnorm(100, mean=0), rnorm(200, mean=0.5), fun=f.Q1, R=1e3)$p.value
19+
#'
20+
#' @export
21+
#'
22+
compare.two.sample <- function(sample1, sample2, fun=mean, R=1000) {
23+
24+
b <- simpleboot::two.boot(sample1, sample2, fun, R = R)
25+
26+
p.value <- max(min(mean(b$t >=0), mean(b$t <= 0)),1/R)*2
27+
28+
list(object=b, p.value=p.value)
29+
}

0 commit comments

Comments
 (0)