The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.
This short vignette provides coding examples on how to use the
functions provided by the aquacultuR package to calculate
growth metrics commonly used in the field of
aquaculture.
library(aquacultuR)
library(magrittr)
library(dplyr)
library(tidyr)
library(lubridate)
oldopts <- options()
options(digits = 3)
The data we will assess in order to demonstrate the calculation of growth and feed conversion metrics originates from one out of two experiments during with Atlantic salmon (Salmo salar) has been exposed to different levels of dissolved oxygen saturation. The original data was published by Liland et al. (2024). The original Excel workbook and can be found together with additional information in the dedicated publication. The data has been tidied by converting the double-row into single-row column names. More information on tidy data can be found for instance in Wickham (2014). In addition, proximate and amino acid compositions have been converted from percentages to mass fractions in gram per gram.
To calculate growth and the zootechnical metrics related to it, we generally need data related to the
The weight data is recorded in the
samplings dataset.
head(samplings)
#> # A tibble: 6 × 14
#> date tank replicate sample_type fish_weight fork_length liver_weight
#> <date> <fct> <fct> <fct> <dbl> <dbl> <dbl>
#> 1 2023-03-16 T1 1 bulk 295 NA NA
#> 2 2023-03-16 T2 1 bulk 315 NA NA
#> 3 2023-03-16 T3 1 bulk 328 NA NA
#> 4 2023-03-16 T6 1 bulk 332 NA NA
#> 5 2023-03-16 T7 1 bulk 310 NA NA
#> 6 2023-03-16 T8 1 bulk 309 NA NA
#> # ℹ 7 more variables: hsi <dbl>, heart_weight <dbl>, csi <dbl>,
#> # gonad_weight <dbl>, gsi <dbl>, viscera_weight <dbl>, vsi <dbl>
Water parameters, meanwhile, are recorded in the
water_params dataset.
head(water_params)
#> # A tibble: 6 × 6
#> date tank temp salinity do_perc do_conc
#> <date> <chr> <dbl> <dbl> <dbl> <dbl>
#> 1 2023-03-16 T1 12.1 22.6 60.4 5.62
#> 2 2023-03-16 T2 12.3 22.6 60.2 5.58
#> 3 2023-03-16 T3 12.2 22.6 56.3 5.23
#> 4 2023-03-16 T6 12.1 22 63.1 5.88
#> 5 2023-03-16 T7 12.2 22 63.5 5.91
#> 6 2023-03-16 T8 12.1 22 65.4 6.1
Both datasets share the date and tank
column and can be merged by them.
To calculate some metrics related to fish growth, we are interested in the fish weight at the beginning and the end of the experiment for each tank, which is exactly the data that the dataset provides. Therefore, we do not need to filter the dataset. However, we will add an additional column that specifies the timepoint in relation to the date and will make our life easier later on and calculate the mean and standard deviation per tank.
df <- samplings %>%
mutate(timepoint = case_when(
date == ymd("2023-03-16") ~ "beginning",
date == ymd("2023-04-14") ~ "end",
.default = NA
)) %>%
group_by(tank, timepoint, sample_type) %>%
summarise(mean_weight = mean(fish_weight),
sd_weight = sd(fish_weight)) %>%
print()
#> `summarise()` has grouped output by 'tank', 'timepoint'. You can override using
#> the `.groups` argument.
#> # A tibble: 18 × 5
#> # Groups: tank, timepoint [18]
#> tank timepoint sample_type mean_weight sd_weight
#> <fct> <chr> <fct> <dbl> <dbl>
#> 1 T1 beginning bulk 295 NA
#> 2 T1 end individual 385. 127.
#> 3 T10 beginning bulk 313 NA
#> 4 T10 end individual 385. 133.
#> 5 T11 beginning bulk 305 NA
#> 6 T11 end individual 369. 122.
#> 7 T2 beginning bulk 315 NA
#> 8 T2 end individual 394. 113.
#> 9 T3 beginning bulk 328 NA
#> 10 T3 end individual 370. 95.5
#> 11 T6 beginning bulk 332 NA
#> 12 T6 end individual 398. 133.
#> 13 T7 beginning bulk 310 NA
#> 14 T7 end individual 402. 121.
#> 15 T8 beginning bulk 309 NA
#> 16 T8 end individual 417. 132.
#> 17 T9 beginning bulk 305 NA
#> 18 T9 end individual 378. 131.
The initial weighing was done in bulk per tank, which is why there was no standard deviation calculated for the respective time points. Now we convert the data into wide format and calculate the duration of the experiment.
df <- df %>%
select(-sample_type, -starts_with("sd")) %>%
pivot_wider(
names_from = timepoint,
values_from = c(mean_weight),
names_vary = "slowest"
) %>%
mutate(duration = as.numeric(max(samplings$date) - min(samplings$date))) %>%
print()
#> # A tibble: 9 × 4
#> # Groups: tank [9]
#> tank beginning end duration
#> <fct> <dbl> <dbl> <dbl>
#> 1 T1 295 385. 29
#> 2 T10 313 385. 29
#> 3 T11 305 369. 29
#> 4 T2 315 394. 29
#> 5 T3 328 370. 29
#> 6 T6 332 398. 29
#> 7 T7 310 402. 29
#> 8 T8 309 417. 29
#> 9 T9 305 378. 29
After data preparation, we can now calculate some growth-related
metrics, including the Absolute Growth (AG) with the
ag() function, the Relative Growth (RG)
with the rg() function, and the time-related
Absolute Growth Rate (AGR) using the agr()
function. A special case is the Relative Growth Rate
(RGR) that is calculated with the rgr() function. Note that
the denominator of the Relative Growth Rate is calculated by default by
applying the geometric mean, but the arithmetic mean can also be used.
Lastly, we also calculate the Specific Growth Rate
(SGR) with the sgr() function.
df %>%
group_by(tank) %>%
mutate(
absolute_growth = ag(ibw = beginning, fbw = end),
relative_growth = rg(ibw = beginning, fbw = end),
absolute_growth_rate = agr(ibw = beginning, fbw = end, duration),
specific_growth_rate = sgr(ibw = beginning, fbw = end, duration)
)
#> # A tibble: 9 × 8
#> # Groups: tank [9]
#> tank beginning end duration absolute_growth relative_growth
#> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 T1 295 385. 29 90.4 0.307
#> 2 T10 313 385. 29 71.5 0.229
#> 3 T11 305 369. 29 63.8 0.209
#> 4 T2 315 394. 29 78.9 0.251
#> 5 T3 328 370. 29 41.6 0.127
#> 6 T6 332 398. 29 65.6 0.198
#> 7 T7 310 402. 29 92.1 0.297
#> 8 T8 309 417. 29 108. 0.351
#> 9 T9 305 378. 29 73.1 0.240
#> # ℹ 2 more variables: absolute_growth_rate <dbl>, specific_growth_rate <dbl>
df %>%
group_by(tank) %>%
mutate(
geometric_bodyweight = gbw(ibw = beginning, fbw = end),
relative_growth_rate_geom = rgr(
ibw = beginning,
fbw = end,
duration,
mean_fun = "geometric"
),
relative_growth_rate_arith = rgr(
ibw = beginning,
fbw = end,
duration,
mean_fun = "arithmetic"
)
)
#> # A tibble: 9 × 7
#> # Groups: tank [9]
#> tank beginning end duration geometric_bodyweight relative_growth_rate_geom
#> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 T1 295 385. 29 337. 0.00925
#> 2 T10 313 385. 29 347. 0.00711
#> 3 T11 305 369. 29 335. 0.00656
#> 4 T2 315 394. 29 352. 0.00773
#> 5 T3 328 370. 29 348. 0.00412
#> 6 T6 332 398. 29 363. 0.00622
#> 7 T7 310 402. 29 353. 0.00900
#> 8 T8 309 417. 29 359. 0.0104
#> 9 T9 305 378. 29 340. 0.00742
#> # ℹ 1 more variable: relative_growth_rate_arith <dbl>
To calculate the Thermal Growth Coefficient (TGC)
with the tgc() function, we need to add temperature data,
which is supplied in the water_params dataset. We will thus
join this dataset into our growth dataset after calculating the average
temperature throughout the experiment.
# 1. calculate mean temperature
# 2. join into growth data
# 3. calculate TGC
water_params %>%
group_by(tank) %>%
summarise(temp = mean(temp)) %>%
right_join(df, join_by(tank)) %>%
mutate(
thermal_growth_coefficient = tgc(
ibw = beginning,
fbw = end,
duration = duration,
temp = temp
))
#> # A tibble: 9 × 6
#> tank temp beginning end duration thermal_growth_coefficient
#> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 T1 12.1 295 385. 29 1.77
#> 2 T10 11.7 313 385. 29 1.42
#> 3 T11 11.8 305 369. 29 1.29
#> 4 T2 12.3 315 394. 29 1.48
#> 5 T3 12.2 328 370. 29 0.790
#> 6 T6 12.1 332 398. 29 1.22
#> 7 T7 12.2 310 402. 29 1.73
#> 8 T8 12.0 309 417. 29 2.04
#> 9 T9 11.6 305 378. 29 1.48
sessionInfo()
#> R version 4.5.2 (2025-10-31)
#> Platform: x86_64-apple-darwin20
#> Running under: macOS Sequoia 15.7.3
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.5-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
#>
#> locale:
#> [1] C/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: Europe/Prague
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] lubridate_1.9.4 tidyr_1.3.2 dplyr_1.1.4 magrittr_2.0.4
#> [5] aquacultuR_1.1.1
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.7.0 cli_3.6.5 knitr_1.51 rlang_1.1.7
#> [5] xfun_0.56 otel_0.2.0 purrr_1.2.1 generics_0.1.4
#> [9] jsonlite_2.0.0 glue_1.8.0 htmltools_0.5.9 sass_0.4.10
#> [13] rmarkdown_2.30 evaluate_1.0.5 jquerylib_0.1.4 tibble_3.3.1
#> [17] fastmap_1.2.0 yaml_2.3.12 lifecycle_1.0.5 compiler_4.5.2
#> [21] timechange_0.3.0 pkgconfig_2.0.3 rstudioapi_0.18.0 digest_0.6.39
#> [25] R6_2.6.1 utf8_1.2.6 tidyselect_1.2.1 pillar_1.11.1
#> [29] bslib_0.9.0 withr_3.0.2 tools_4.5.2 cachem_1.1.0
options(oldopts)
These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.