ageBias {FSA} | R Documentation |

Constructs age-agreement tables, statistical tests to detect differences, and plots to visualize potential differences in paired age estimates. Ages may be from, for example, two readers of the same structure, one reader at two times, two structures (e.g., scales, spines, otoliths), or one structure and known ages.

ageBias(formula, data, ref.lab = tmp$Enames, nref.lab = tmp$Rname, method = stats::p.adjust.methods, sig.level = 0.05, min.n.CI = 3) ## S3 method for class 'ageBias' summary(object, what = c("table", "symmetry", "Bowker", "EvansHoenig", "McNemar", "bias", "diff.bias", "n"), flip.table = FALSE, zero.print = "-", digits = 3, cont.corr = c("none", "Yates", "Edwards"), ...) ## S3 method for class 'ageBias' plot(x, xvals = c("reference", "mean"), xlab = ifelse(xvals == "reference", x$ref.lab, "Mean Age"), ylab = paste(x$nref.lab, "-", x$ref.lab), xlim = NULL, ylim = NULL, yaxt = graphics::par("yaxt"), xaxt = graphics::par("xaxt"), col.agree = "gray60", lwd.agree = lwd, lty.agree = 2, lwd = 1, sfrac = 0, show.pts = NULL, pch.pts = 20, cex.pts = ifelse(xHist | yHist, 1.5, 1), col.pts = "black", transparency = 1/10, show.CI = FALSE, col.CI = "black", col.CIsig = "red", lwd.CI = lwd, sfrac.CI = sfrac, show.range = NULL, col.range = ifelse(show.CI, "gray70", "black"), lwd.range = lwd, sfrac.range = sfrac, pch.mean = 19, pch.mean.sig = ifelse(show.CI | show.range, 21, 19), cex.mean = lwd, yHist = TRUE, xHist = NULL, hist.panel.size = 1/7, col.hist = "gray90", allowAdd = FALSE, ...) plotAB(x, what = c("bias", "Campana", "numbers"), xlab = x$ref.lab, ylab = x$nref.lab, xlim = NULL, ylim = NULL, yaxt = graphics::par("yaxt"), xaxt = graphics::par("xaxt"), col.agree = "gray60", lwd.agree = lwd, lty.agree = 2, lwd = 1, sfrac = 0, pch.mean = 19, pch.mean.sig = 21, cex.mean = lwd, col.CI = "black", col.CIsig = "red", lwd.CI = lwd, sfrac.CI = sfrac, show.n = FALSE, nYpos = 1.03, cex.n = 0.75, cex.numbers = 0.75, col.numbers = "black", ...)

`formula` |
A formula of the form |

`data` |
A data.frame that minimally contains the paired age estimates given in |

`ref.lab` |
A string label for the reference age estimates. |

`nref.lab` |
A string label for the nonreference age estimates. |

`method` |
A string for which method to use to adjust p-values for multiple comparisons. See |

`sig.level` |
A numeric value to determine whether a p-value indicates a significant result. The confidence level used in |

`min.n.CI` |
A numeric value (default is 3) that is the smallest sample size for which a confidence interval will be computed. |

`what` |
A string that indicates what type of summary to print or plot to construct. See details. |

`flip.table` |
A logical that indicates whether the age-agreement table should be ‘flipped’ (i.e., rows are reversed so that younger ages are at the bottom of the table). This makes the table more directly comparable to the age bias plot. |

`zero.print` |
A string for what should be printed in place of the zeros on an age-agreement table. The default is to print a single dash. |

`digits` |
A numeric for the minimum number of digits to print when showing |

`cont.corr` |
A string that indicates the continuity correction method to be used with (only) McNemar test. If |

`...` |
Additional arguments for methods. |

`x, object` |
An object of class |

`xvals` |
A string for whether the x-axis values are reference ages or mean of the reference and nonreference ages. |

`xlab, ylab` |
A string label for the x-axis (reference) or y-axis (non-reference) age estimates, respectively. |

`xlim, ylim` |
A numeric vector of length 2 that contains the limits of the x-axis (reference ages) or y-axis (non-reference ages), respectively. |

`xaxt, yaxt` |
A string which specifies the x- and y-axis types. Specifying “n” suppresses plotting of the axis. See |

`col.agree` |
A string or numeric for the color of the 1:1 or zero (if |

`lwd.agree` |
A numeric for the line width of the 1:1 or zero (if |

`lty.agree` |
A numeric for the line type of the 1:1 or zero (if |

`lwd` |
A numeric that controls the separate ‘lwd’ argument (e.g., |

`sfrac` |
A numeric that controls the separate ‘sfrac’ arguments (e.g., |

`show.pts` |
A logical for whether or not the raw data points are plotted. |

`pch.pts` |
A numeric for the plotting character of the raw data points. |

`cex.pts` |
A character expansion value for the size of the symbols for |

`col.pts` |
A string or numeric for the color of the raw data points. The default is to use black with the transparency found in |

`transparency` |
A numeric (between 0 and 1) for the level of transparency of the raw data points. This number of points plotted on top of each other will represent the color in |

`show.CI` |
A logical for whether confidence intervals should be plotted or not. |

`col.CI` |
A string or numeric for the color of confidence interval bars that are considered non-significant. |

`col.CIsig` |
A string or numeric for the color of confidence interval bars that are considered significant. |

`lwd.CI` |
A numeric for the line width of the confidence interval bars. |

`sfrac.CI` |
A numeric for the size of the ends of the confidence interval bars. See |

`show.range` |
A logical for whether or not vertical bars that represent the range of the data points are plotted. |

`col.range` |
A string or numeric for the color of the range intervals. |

`lwd.range` |
A numeric for the line width of the range intervals. |

`sfrac.range` |
A numeric for the size of the ends of the range intervals. See |

`pch.mean` |
A numeric for the plotting character used for the mean values when the means are considered insignificant. |

`pch.mean.sig` |
A numeric for the plotting character for the mean values when the means are considered significant. |

`cex.mean` |
A character expansion value for the size of the mean symbol in |

`yHist` |
A logical for whether a histogram of the y-axis variable should be added to the right margin of the age bias plot. See details. |

`xHist` |
A logical for whether a histogram of the x-axis variable should be added to the top margin of the age bias plot. See details. |

`hist.panel.size` |
A numeric between 0 and 1 that indicates the proportional size of histograms (relative to the entire plotting pane) in the plot margins (only used if |

`col.hist` |
A string for the color of the bars in the marginal histograms (only used if |

`allowAdd` |
A logical that will allow the user to add items to the main (i.e., not the marginal histograms) plot panel (if |

`show.n` |
A logical for whether the sample sizes for each level of the x-axis variable is shown ( |

`nYpos` |
A numeric for the relative Y position of the sample size values when |

`cex.n` |
A character expansion value for the size of the sample size values. |

`cex.numbers` |
A character expansion value for the size of the numbers plotted when |

`col.numbers` |
A string for the color of the numbers plotted when |

Generally, one of the two age estimates will be identified as the “reference” set. In some cases this may be the true ages, the ages from the more experienced reader, the ages from the first reading, or the ages from the structure generally thought to provide the most accurate results. In other cases, such as when comparing two novice readers, the choice may be arbitrary. The reference ages will form the columns of the age-agreement table and will be the “constant” age used in the t-tests and age bias plots (i.e., the x-axis). See further details below.

The age-agreement table is constructed with `what="table"`

in `summary`

. The agreement table can be “flipped” (i.e., the rows in descending rather than ascending order) with `flip.table=TRUE`

. By default, the tables are shown with zeros replaced by dashes. This behavior can be changed with `zero.print`

.

Three statistical tests of symmetry for the age-agreement table can be computed with `what=`

in `summary`

. The “unpooled” or Bowker test as described in Hoenig et al. (1995) is constructed with `what="Bowker"`

, the “semi-pooled” or Evans-Hoenig test as described in Evans and Hoenig (1998) is constructed with `what="EvansHoenig"`

, and the “pooled” or McNemar test as described in Evans and Hoenig (1998) is constructed with `what="McNemar"`

. All three tests are computed with `what="symmetry"`

.

Four types of plots for visualizing differences between sets of two age estimates may be created. Two of these plots may be constructed with `plotAB()`

. In the `plotAB()`

plots, the reference ages are plotted on the x-axis and the nonreference ages are on the y-axis. The 1:1 (45 degree) agreement line is shown for comparative purposes. The default `plotAB()`

plot (using `what="bias"`

) was inspired by the age bias plot introduced by Campana et al. (1995). The default settings for this age bias plot show the mean and confidence interval for the nonreference ages at each of the reference ages. The level of confidence is controlled by `sig.level=`

given in the original `ageBias`

call (i.e., confidence level is 100*(1-`sig.level`

)). Confidence intervals are only shown if the sample size is greater than the value in `min.n.CI=`

(also from the original call to `ageBias`

). Confidence intervals plotted in red with an open dot (by default; these can be changed with `col.CIsig`

and `pch.mean.sig`

, respectively) do not contain the reference age (see discussion of t-tests below). Sample sizes at each reference age are shown if `show.n=TRUE`

. The position of the sample sizes is controlled with `nYpos=`

, whereas their size is controlled with `cex.n`

. Arguments may be used to nearly replicate the age bias plot as introduced by Campana et al. (1995) as shown in the examples.

The frequency of observations at each unique (x,y) coordinate are shown by using `what="numbers"`

in `plotAB`

. The size of the numbers is controlled with `cex.numbers`

.

Muir et al. (2008) modified the age bias plot by plotting the difference between the two ages on the y-axis (still against a reference age on the x-axis). McBride (2015) introduced the Bland-Altman plot for comparing fish ages where the difference in ages is plotted on the y-axis versus the mean of the ages on the x-axis. Modifications of these plots are created with `plot`

(rather than `plotAB`

) using `xvals=`

to control what is plotted on the x-axis (i.e., `xvals="reference"`

uses the reference ages, whereas `xvals="mean"`

uses the mean of the two ages for the x-axis). In both plots, a horizontal agreement line at a difference of zero is shown for comparative purposes. In addition, a histogram of the differences is shown in the right margin (can be excluded with `yHist=FALSE`

.) A histogram of the reference ages is shown by default in the top margin for the modified age bias plot, but not for the modified Bland-Altman-like plot (the presence of this histogram is controlled with `xHist=`

).

By default, the modified age bias plot shows the mean and range for the nonreference ages at each of the reference ages. Means shown with an open dot are mean age differences that are significantly different from zero. The ranges of differences in ages at each reference age can be removed with `show.range=FALSE`

. A confidence interval for difference in ages can be added with `show.CI=FALSE`

. The color and symbol coding for the means and CIs is the same as described above for `plotAB`

. Individual points are plotted if `show.pts=TRUE`

, where there color is controlled by `col.pts=`

and `transparency=`

. See examples for use of these arguments.

Both the main (i.e., not the marginal histograms) can be "added to" after the plot is constructed if `allowAdd=TRUE`

is used. For example, the Bland-Altman-like plot can be augmented with a horizontal line at the mean difference in ages, a line for the regression between the differences and the means, or a generalized additive model that describes the relationship between the differences and the means. See the examples for use of `allowAdd=TRUE`

. It is recommended to save the plotting parameters (e.g., `op <- par(no.readonly=TRUE)`

) before using `plot`

with `allowAdd=TRUE`

so that the original parameters can be reset (e.g., `par(op)`

); see the examples.

Individual t-tests to determine if the mean age of the nonreference set at a particular age of the reference set is equal to the reference age (e.g., is the mean age of the nonreference set at age-3 of the reference set statistically different from 3?) are shown with `what="bias"`

in `summary`

. The results provide a column that indicates whether the difference is significant or not as determined by adjusted p-values from the t-tests and using the significance level provided in `sig.level`

(defaults to 0.05). Similar results for the difference in ages (e.g., is the mean reference age minus nonreference age at a nonreference age of 3 different from 0?) are constructed with `what="diff.bias"`

in `summary`

.

The sample size present in the age-agreement table is found with `what="n"`

.

`ageBias`

returns a list with the following items:

data A data.frame with the original paired age estimates and the difference between those estimates.

agree The age-agreement table.

bias A data.frame that contains the bias statistics.

bias.diff A data.frame that contains the bias statistics for the differences.

ref.lab A string that contains an optional label for the age estimates in the columns (reference) of the age-agreement table.

nref.lab A string that contains an optional label for the age estimates in the rows (non-reference) of the age-agreement table.

`summary`

returns the result if `what=`

contains one item, otherwise it returns nothing. Nothing is returned by `plot`

or `plotAB`

, but see details for a description of the plot that is produced.

Tested all symmetry test results against results in Evans and Hoenig (2008), the McNemar and Evans-Hoenig results against results from `compare2`

in fishmethods, and all results using the `AlewifeLH`

data set from FSAdata against results from the online resource at http://www.nefsc.noaa.gov/fbp/age-prec/.

4-Age Comparisons. **Note that plot has changed since IFAR was published. Some of the original functionality is in plotAB. See examples.**

Derek H. Ogle, derek@derekogle.com

Ogle, D.H. 2016. Introductory Fisheries Analyses with R. Chapman & Hall/CRC, Boca Raton, FL.

Campana, S.E., M.C. Annand, and J.I. McMillan. 1995. Graphical and statistical methods for determining the consistency of age determinations. Transactions of the American Fisheries Society 124:131-138. [Was (is?) available from http://www.bio.gc.ca/otoliths/documents/Campana%20et%20al%201995%20TAFS.pdf.]

Evans, G.T. and J.M. Hoenig. 1998. Testing and viewing symmetry in contingency tables, with application to readers of fish ages. Biometrics 54:620-629.

Hoenig, J.M., M.J. Morgan, and C.A. Brown. 1995. Analysing differences between two age determination methods by tests of symmetry. Canadian Journal of Fisheries and Aquatic Sciences 52:364-368.

McBride, R.S. 2015. Diagnosis of paired age agreement: A simulation approach of accuracy and precision effects. ICES Journal of Marine Science 72:2149-2167.

Muir, A.M., M.P. Ebener, J.X. He, and J.E. Johnson. 2008. A comparison of the scale and otolith methods of age estimation for lake whitefish in Lake Huron. North American Journal of Fisheries Management 28:625-635. [Was (is?) available from http://www.tandfonline.com/doi/abs/10.1577/M06-160.1]

See `agePrecision`

for measures of precision between pairs of age estimates. See `compare2`

in fishmethods for similar functionality.

data(WhitefishLC) ab1 <- ageBias(scaleC~otolithC,data=WhitefishLC,ref.lab="Otolith Age",nref.lab="Scale Age") summary(ab1) summary(ab1,what="symmetry") summary(ab1,what="Bowker") summary(ab1,what="EvansHoenig") summary(ab1,what="McNemar") summary(ab1,what="McNemar",cont.corr="Yates") summary(ab1,what="bias") summary(ab1,what="diff.bias") summary(ab1,what="n") summary(ab1,what=c("n","symmetry","table")) # show the zeros (rather than dashes) summary(ab1,what="table",zero.print="0") # flip the table -- ease of comparison to age bias plot summary(ab1,what="table",flip.table=TRUE) ############################################################# ## Traditional Age-Bias Plot (from Campana et al. (1995)) # Default plotAB(ab1) # very close to Campana et al. (2001) plotAB(ab1,pch.mean.sig=19,col.CIsig="black",sfrac=0.01) # Squared up the axes plotAB(ab1,pch.mean.sig=19,col.CIsig="black",ylim=c(-1,23),xlim=c(-1,23)) ## Show sample sizes plotAB(ab1,show.n=TRUE) ## Move sample sizes (and change text size) plotAB(ab1,show.n=TRUE,nYpos=0.02,cex.n=0.5) ## Traditional numbers plot plotAB(ab1,what="numbers") ############################################################# ## Differences Plot (originally inspired by Muir et al. (2008)) # Default (ranges, open circles for sig diffs, marginal hists) plot(ab1) # Show CIs for means (with and without ranges) plot(ab1,show.CI=TRUE) plot(ab1,show.CI=TRUE,show.range=FALSE) # show points (with and without CIs) plot(ab1,show.CI=TRUE,show.range=FALSE,show.pts=TRUE) plot(ab1,show.range=FALSE,show.pts=TRUE) # Use same symbols for all means (with ranges) plot(ab1,pch.mean.sig=19) # Use same symbols/colors for all means/CIs (without ranges) plot(ab1,show.range=FALSE,show.CI=TRUE,pch.mean.sig=19,col.CIsig="black") # Remove histograms plot(ab1,xHist=FALSE) plot(ab1,yHist=FALSE) plot(ab1,xHist=FALSE,yHist=FALSE) ## Suppress confidence intervals for n < a certain value ## must set this in the original ageBias() call ab2 <- ageBias(scaleC~otolithC,data=WhitefishLC,min.n.CI=8, ref.lab="Otolith Age",nref.lab="Scale Age") plot(ab2,show.CI=TRUE,show.range=FALSE) ############################################################# ## Differences Plot (originally inspired by Bland-Altman plots ## in McBride (2015)) plot(ab1,xvals="mean") ## Modify axis limits plot(ab1,xvals="mean",xlim=c(1,17)) ## Add and remove histograms plot(ab1,xvals="mean",xHist=TRUE) plot(ab1,xvals="mean",xHist=TRUE,yHist=FALSE) plot(ab1,xvals="mean",yHist=FALSE) ############################################################# ## Adding post hoc analyses to the main plot # get original graphing parameters to be reset at the end op <- par(no.readonly=TRUE) # get raw data tmp <- ab1$d head(tmp) # Add mean difference (w/ approx. 95% CI) bias <- mean(tmp$diff)+c(-1.96,0,1.96)*se(tmp$diff) plot(ab1,xvals="mean",xlim=c(1,17),allowAdd=TRUE) abline(h=bias,lty=2,col="red") par(op) # Same as above, but without margoinal histogram, and with # 95% agreement lines as well (1.96SDs) # (this is nearly a replicate of a Bland-Altman plot) bias <- mean(tmp$diff)+c(-1.96,0,1.96)*se(tmp$diff) agline <- mean(tmp$diff)+c(-1.96,1.96)*sd(tmp$diff) plot(ab1,xvals="mean",yHist=FALSE,allowAdd=TRUE) abline(h=bias,lty=2,col="red") abline(h=agline,lty=3,lwd=2,col="blue") par(op) # Add linear regression line of differences on means (w/ approx. 95% CI) lm1 <- lm(diff~mean,data=tmp) xval <- seq(0,19,0.1) pred1 <- predict(lm1,data.frame(mean=xval),interval="confidence") bias1 <- data.frame(xval,pred1) head(bias1) plot(ab1,xvals="mean",xlim=c(1,17),allowAdd=TRUE) lines(lwr~xval,data=bias1,lty=2,col="red") lines(upr~xval,data=bias1,lty=2,col="red") lines(fit~xval,data=bias1,lty=2,col="red") par(op) # Add loess of differences on means (w/ approx. 95% CI as a polygon) lo2 <- loess(diff~mean,data=tmp) xval <- seq(min(tmp$mean),max(tmp$mean),0.1) pred2 <- predict(lo2,data.frame(mean=xval),se=TRUE) bias2 <- data.frame(xval,pred2) bias2$lwr <- bias2$fit-1.96*bias2$se.fit bias2$upr <- bias2$fit+1.96*bias2$se.fit head(bias2) plot(ab1,xvals="mean",xlim=c(1,17),allowAdd=TRUE) with(bias2,polygon(c(xval,rev(xval)),c(lwr,rev(upr)), col=col2rgbt("red",1/10),border=NA)) lines(fit~xval,data=bias2,lty=2,col="red") par(op) # Same as above, but polygon and line behind the points plot(ab1,xvals="mean",xlim=c(1,17),col.pts="white",allowAdd=TRUE) with(bias2,polygon(c(xval,rev(xval)),c(lwr,rev(upr)), col=col2rgbt("red",1/10),border=NA)) lines(fit~xval,data=bias2,lty=2,col="red") points(diff~mean,data=tmp,pch=19,col=col2rgbt("black",1/8)) par(op) # Can also be made with the reference ages on the x-axis lo3 <- loess(diff~otolithC,data=tmp) xval <- seq(min(tmp$otolithC),max(tmp$otolithC),0.1) pred3 <- predict(lo3,data.frame(otolithC=xval),se=TRUE) bias3 <- data.frame(xval,pred3) bias3$lwr <- bias3$fit-1.96*bias3$se.fit bias3$upr <- bias3$fit+1.96*bias3$se.fit plot(ab1,show.range=FALSE,show.pts=TRUE,col.pts="white",allowAdd=TRUE) with(bias3,polygon(c(xval,rev(xval)),c(lwr,rev(upr)), col=col2rgbt("red",1/10),border=NA)) lines(fit~xval,data=bias3,lty=2,col="red") points(diff~otolithC,data=tmp,pch=19,col=col2rgbt("black",1/8)) par(op)

[Package *FSA* version 0.8.18 Index]