Age Precision and Bias — Changes to FSA
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Last week I taught part of a workshop for the Minnesota Chapter of the American Fisheries Society on “Analyzing Age Data in R” (materials are here). I like doing these workshops because they give me ideas for improving the FSA package and fishR. One of several things that came out of this workshop was a realization that the measures of precision for multiple age assignments on individual fish (think two or more “readers” assigning an age to each fish) that I had coded in ageComp()
was restricted to only two age assignments. The methods as described in the literature generalize to two or more age assignments. My code had to change!
The latest version of the FSA package now has two new functions, ageBias()
and agePrecision()
, which replace ageComp()
(ageComp()
currently remains in FSA but will be removed in future versions, so you should begin changing your usage now). I have not yet updated the “Age Comparisons Vignette” on fishR (I want to make major changes to all of the content in that vignette, not just the R part), so I will briefly demonstrate the new functions in this post.
Obviously, I need to load the FSA package.
library(FSA)
I will use the information in the WhitefishLC
data frame which has age assignments for three structures (otoliths, finrays, and scales) made by two readers (1 and 2). The readers also came to a concensus age (labeled with a “C”).
data(WhitefishLC) str(WhitefishLC) ## 'data.frame': 151 obs. of 11 variables: ## $ fishID : int 1 2 3 4 5 6 7 8 9 10 ... ## $ tl : int 345 334 348 300 330 316 508 475 340 173 ... ## $ scale1 : int 3 4 7 4 3 4 6 4 3 1 ... ## $ scale2 : int 3 3 5 3 3 4 7 5 3 1 ... ## $ scaleC : int 3 4 6 4 3 4 7 5 3 1 ... ## $ finray1 : int 3 3 3 3 4 2 6 9 2 2 ... ## $ finray2 : int 3 3 3 2 3 3 6 9 3 1 ... ## $ finrayC : int 3 3 3 3 4 3 6 9 3 1 ... ## $ otolith1: int 3 3 3 3 3 6 9 11 3 1 ... ## $ otolith2: int 3 3 3 3 3 5 10 12 4 1 ... ## $ otolithC: int 3 3 3 3 3 6 10 11 4 1 ...
Measures of Precision
Measures of precision are now computed with agePrecision()
which uses formula notation with all variables on the right-hand-side of the formula and separated by “plus”es. Of course, with the formula notation the data=
argument is required. [Note that the measures of precision here are not that useful because of potential bias between the structures; however, these data can be used to illustrate the use of more than two age assignments.]
ap3 <- agePrecision(~otolithC+finrayC+scaleC,data=WhitefishLC)
The overall measures of precision (mean APE, mean CV, and percent total agreement for all structures) are then computed with
summary(ap3,what="precision") ## Precision summary statistics ## n R CV APE PercAgree ## 151 3 21.77 16.19 12.58
The percentages of fish by absolute difference in age assignment for each pair of measures are obtained with
summary(ap3,what="agreement") ## Percentage of fish by differences in ages between pairs of assignments ## 0 1 2 3 4 5 ## otolithC v. finrayC 24.5033 21.1921 17.8808 11.9205 7.2848 7.9470 ## otolithC v. scaleC 19.8675 30.4636 16.5563 13.9073 5.9603 3.3113 ## finrayC v. scaleC 40.3974 34.4371 15.2318 5.2980 3.9735 0.0000 ## 6 7 8 9 10 11 ## otolithC v. finrayC 3.3113 2.6490 0.6623 1.3245 0.0000 0.6623 ## otolithC v. scaleC 5.2980 1.9868 1.3245 0.0000 0.0000 0.6623 ## finrayC v. scaleC 0.6623 0.0000 0.0000 0.0000 0.0000 0.0000 ## 12 13 14 ## otolithC v. finrayC 0.0000 0.0000 0.6623 ## otolithC v. scaleC 0.0000 0.6623 0.0000 ## finrayC v. scaleC 0.0000 0.0000 0.0000
The example above demonstrated the new functionality for more than two age assignments. Of course, two age assignments can still be used
ap2 <- agePrecision(~otolith1+otolith2,data=WhitefishLC) summary(ap2,what="precision") ## Precision summary statistics ## n R CV APE PercAgree ## 151 2 4.719 3.337 62.25 summary(ap2,what="agreement") ## Percentage of fish by differences in ages between pairs of assignments ## 0 1 2 ## 62.25 31.79 5.96
Age Bias
The new code for assessing age bias uses ageBias()
with the same arguments used in the original ageComp()
– i.e., a formula with the age assignments thought to be “more correct” on the left-hand-side, the other age assignment on the right-hand-side, the data=
argument, and column and row labels in col.lab=
and row.lab=
, respectively. The ageBias()
function still only works with two sets of age assignments.
ab1 <- ageBias(otolithC~scaleC,data=WhitefishLC, col.lab="Otolith Age",row.lab="Scale Age")
The overall age agreement table and Bowker’s test for symmetry are computed with
summary(ab1,what="symmetry") ## Raw agreement table (square) ## Otolith Age ## Scale Age 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ## 1 5 4 1 - - - - - - - - - - - - - - - - - - ## 2 4 1 - 1 - - - - - - - - - - - - - - - - - ## 3 - 1 10 6 - 1 - - - - - - - - - - - - - - - ## 4 - - 5 7 3 3 - - - - - - - - - - - - - - - ## 5 - 1 - 3 2 5 3 4 - - 1 - - - - - - - - - - ## 6 - - 1 1 2 1 3 4 1 2 1 1 2 1 - - - - - - - ## 7 - - - - - - 1 3 6 4 2 2 1 1 - - - 1 - - - ## 8 - - - - 1 - 1 1 3 3 3 1 - - - - - - - - - ## 9 - - - - - - - - - - 1 1 1 - 2 - 1 - - - - ## 10 - - - - - - 1 - - - - 1 1 - - 1 - - - - - ## 11 - - - - - - - - - - - - 1 - 1 - 2 - - - - ## 12 - - - - - - - - - - - 1 - - 1 1 - - - - - ## 13 - - - - - - - - - - - - 1 1 - 1 1 1 - - - ## 14 - - - - - - - - - - - - - - 1 - - - 1 - - ## 15 - - - - - - - - - - - - - - - 1 - - - - - ## 16 - - - - - - - - - - - - - - - - - - - - - ## 17 - - - - - - - - - - - - - - - - - - - - - ## 18 - - - - - - - - - - - - - - - - - - - - - ## 19 - - - - - - - - - - - - - - - - - - - - - ## 20 - - - - - - - - - - - - - - - - - - - - - ## 21 - - - - - - - - - - - - - - - - - - - - - ## 22 - - - - - - - - - - - - - - - - - - - - - ## 23 - - - - - - - - - - - - - - - - - - - - - ## Otolith Age ## Scale Age 22 23 ## 1 - - ## 2 - - ## 3 - - ## 4 - - ## 5 - - ## 6 - - ## 7 - - ## 8 - - ## 9 - - ## 10 - 1 ## 11 - - ## 12 - - ## 13 - - ## 14 - - ## 15 - - ## 16 - - ## 17 - - ## 18 - - ## 19 - - ## 20 - - ## 21 - - ## 22 - - ## 23 - - ## ## Bowker's (Hoenig's) Test of Symmetry ## df chi.sq p ## 54 75.98 0.02598
The summary statistics, t-test results, and confidence intervals for the “other” (row) age assignments at each age of the “more correct” (column) age assignments are obtained with
summary(ab1,what="bias") ## Summary of Scale Age by Otolith Age ## otolithC n min max mean SE t adj.p sig LCI UCI ## 1 9 1 2 1.44 0.176 2.530 0.21160 FALSE 1.039 1.85 ## 2 7 1 5 2.00 0.577 0.000 1.00000 FALSE 0.587 3.41 ## 3 17 1 6 3.35 0.242 1.460 0.81763 FALSE 2.841 3.87 ## 4 18 2 6 3.83 0.232 -0.718 1.00000 FALSE 3.343 4.32 ## 5 8 4 8 5.25 0.491 0.509 1.00000 FALSE 4.089 6.41 ## 6 10 3 6 4.60 0.267 -5.250 0.00528 TRUE 3.997 5.20 ## 7 9 5 10 6.44 0.556 -1.000 1.00000 FALSE 5.163 7.73 ## 8 12 5 8 6.08 0.288 -6.665 0.00042 TRUE 5.450 6.72 ## 9 10 6 8 7.20 0.200 -8.999 0.00011 TRUE 6.748 7.65 ## 10 9 6 8 7.11 0.261 -11.087 0.00005 TRUE 6.510 7.71 ## 11 8 5 9 7.25 0.453 -8.275 0.00081 TRUE 6.178 8.32 ## 12 7 6 12 8.43 0.782 -4.564 0.03450 TRUE 6.514 10.34 ## 13 7 6 13 8.86 1.010 -4.101 0.05079 FALSE 6.385 11.33 ## 14 3 6 13 8.67 NA NA NA FALSE NA NA ## 15 5 9 14 11.00 0.949 -4.216 0.09462 FALSE 8.366 13.63 ## 16 4 10 15 12.50 NA NA NA FALSE NA NA ## 17 4 9 13 11.00 NA NA NA FALSE NA NA ## 18 2 7 13 10.00 NA NA NA FALSE NA NA ## 19 1 14 14 14.00 NA NA NA FALSE NA NA ## 23 1 10 10 10.00 NA NA NA FALSE NA NA
The default age-bias plot is provided with
plot(ab1)
I changed the code for the age-bias plot so that confidence intervals are not computed for ages with “small” sample sizes. The definition of small can be controlled with min.n.CI=
(which defaults to 5) in the ageBias()
call. For example, the default age-bias plot from the original ageComp()
is constructed with
ab2 <- ageBias(otolithC~scaleC,data=WhitefishLC,min.n.CI=2, col.lab="Otolith Age",row.lab="Scale Age") plot(ab2)
This is, of course, quite ugly. I also modified the code to more sensibly handle controlling the axes in situations like this. For example,
plot(ab2,ylim=c(0,23))
More details are in the help files for ageBias()
and agePrecision()
. Let me know if you have any questions or comments.
Filed under: Fisheries Science, R Tagged: "Age Bias", "Precision, Age, Age Comparisons", R
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.