In a previous post I demonstrated how to make a plot that illustrated the fit of a von Bertalanffy growth function (VBGF) to data. In this post, I will demonstrate how to show the VBGF fits for two or more groups (e.g., sexes, locations, years). Here I will again use the lengths and ages of Lake Erie Walleye (Sander vitreus) captured during October-November, 2003-2014. These data are available in my FSAdata package and formed many of the examples in Chapter 12 of the Age and Growth of Fishes: Principles and Techniques book. My primary interest is in the tl (total length in mm), age, and sex variables (see here for more details). I will focus initially on Walleye from location “1” captured in 2014 (as an example).
The workflow below requires the predict2() and vb() functions that were created in the previous post.
Fitting all von Bertalanffy Growth Functions
The key to constructing plots with multiple VBGF trajectories is to create a “long format” data.frame of predicted mean lengths-at-age with associated bootstrap confidence intervals. In this format one row corresponds to a single “group” and age with columns (variabls) that identify the “group”, age”, predicted mean length, and the lower and upper values for the confidence interval. There is likely many ways to construct such a data.frame, but a loop over the “groups” (i.e., sexes) is used below
Begin by finding the range of ages for both sexes so that the confidence polygon can be restricted to observed ages.
To simplify coding below, the levels and number of “groups” are saved into objects.
In the loop across sexes, the VBGF will be fit for each sex and parameter estimates will be saved into cfs, confidence intervals for the parameter estimates into cis, predicted mean lengths-at-age for all ages considered in preds1, and predicted mean lengths-at-age for only observed ages in preds2. These objects are initialized with NULL prior to starting the loop.1
The code inside the loop follows the same logic as shown in the previous post for fitting the VBGF to one group.2
The cfs, cis, preds1, and preds2 objects will have poorly named rows, columns, or both after the loop. These deficiencies are corrected below.
The preds1 and preds2 objects now contain the predicted mean lengths-at-age with associated confidence intervals in the desired long format.
Multiple VBGFs on One Plot
Constructing the plot with multiple VBGF trajectories is similar to what was shown for one group in the previous post. Note, however, that colors will depend on the sex variable for the confidence polygon because of fill=sex in geom_ribbon(), the points because of color=sex in geom_point(), and the lines because of color=sex in geom_line(). The default colors can be changed in a variety of ways but are set manually to two colors for both fill and color aesthetics below with scale_color_manual().3 Also note that position_dodge() is used in geom_point() to shift the points for the groups slightly left and right to minimize overlap of points between groups. Finally, legend.position= in theme() is used to place the legend inside the plot centered at approximately 80% of the way along the x-axis and 20% of the way up the y-axis, and legend.title= removes the title on the legend (was just the word “sex”).
Some people may prefer to just see model fits. If so, then simply omit geom_point().
Multiple VBGFs in Separate Plots
An alternative to putting multiple VBGF trajectories in one plot is to separate them into individual plots. This is easily handled by including the “grouping” variable name within vars() within facet_wrap().4
Faceting is more interesting when there are more “groups.” The plot below shows different VBGF fits across all available years for female Walleye from location “1.” The code is basically the same as above (i.e., strategically replacing sex with fyear and making sure to use the new data.frame).
BONUS – Plots of Parameter Estimates
A bonus for keeping track of the parameter point and interval estimates through this entire post is to plot the estimates across years. I will leave this up to you to decipher, but note that the years must be added to the cfs and cis data.frames to make the plot shown here.
This is repeated for the other two parameters.
Which can then be neatly placed on top of each other with the patchwork package.
Final Thoughts
I am trying to post examples here as I learn ggplot2. My other ggplot2-related posts can be found here. I will post more about patchwork in future posts.
Footnotes
The parameter estimates and their confidence intervals are not needed to make the plots below; however, they are often of interest so I include them here. ↩
I inclued the notification in cat() as it gives me peace of mind to see where the loop is at. This is useful here because this loop can take a while given the two sets of bootstraps. ↩
I used this resource to help choose two divergent colors that were “color-blind safe.” ↩
All fill=sex and color=sex items were removed from the previous code as leaving them in would result in each facet using a different color (which is redundant with the labels). ↩