The aLBI package provides tools for estimating life
history parameters, length-based indicators, and assessing fish stock
using methods outlined by Cope and Punt (2009) and Froese (2004). These
methods are particularly useful in data-limited situations and for
providing simple indicators to address over-fishing and support
sustainable fisheries management. This simple package facilitates the
estimation of life history parameters of fish only from the length
frequency data. Version 0.1.9 introduces the LWR function
for length-weight relationship analysis and FreqMT for
constructing frequency table for length data of multiple months. This
version also updates FrequencyTable, FsihPar
and FishSS with enhanced functionality. These includes the
addition Monte Carlo, non-parametric bootstrapping, decision making
based on selectivity and saving of outputs to the current working
directory.
The aLBI package offers three primary functions: -
FrequencyTable: Creates a frequency distribution table
for fish length data using either a custom bin width or Wang’s formula
for automatic bin width calculation. The bin width is rounded to the
nearest integer if calculated. - FreqTM: Creates
frequency table for fish length of multiple months using either a custom
bin width or Wang’s formula as described in FrequencyTable
function. - FishPar: This function calculates
length-based indicators using Monte Carlo simulation for length
parameters and non-parametric bootstrap for Froese indicators. -
FishSS: This function assesses the stock status based
on parameters calculated by the FishPar function. -
LWR: Fits and visualizes length-weight relationships
using linear regression.
The package includes functions to calculate various length-based indicators and visualize fish stock data. The approaches from Cope and Punt (2009) are used to establish reference points, while Froese (2004)’s indicators help to evaluate over-fishing status and selectivity. This vignette demonstrates how to use these functions with sample and provided data.
To install the aLBI package from CRAN or GitHub. To enjoy most recent updates, users are encouraged to install the aLBI from GitHub), follow these steps. Note that devtools is required to install packages from GitHub.
# You can install the package using the following commands in your R session:
# Install devtools if you haven't already
# install.packages("devtools")
# # Install dplyr if you haven't already
# install.packages("dplyr")
# # Install readxl if you haven't already
# install.packages("readxl")
# Install ggplot2 if you haven't already
# install.packages("ggplot2")
# Install openxlsx if you haven't already
# install.packages("openxlsx")
# Install rlang if you haven't already
# install.packages("rlang")
# install aLBI package from CRAN
# install.packages("aLBI")
# Install the most updated version of aLBI package from GitHub
# devtools::install_github("Ataher76/aLBI")Ensure the required packages are loaded in your R session. The following code checks for package availability and stops execution with a message if a package is missing.
# Check if required packages are installed and load them
# Check if required packages are installed and load them
required_packages <- c("aLBI", "readxl", "openxlsx", "dplyr", "devtools", "ggplot2", "rlang")
for (pkg in required_packages) {
if (!requireNamespace(pkg, quietly = TRUE)) {
warning(paste("Package", pkg, "is required but not installed."))
} else {
library(pkg, character.only = TRUE)
}
}
#> Loading required package: usethis
# Load the aLBI package
library(aLBI)
library(readxl)
library(dplyr)
library(ggplot2)
library(openxlsx)
library(rlang)
library(devtools)Prepare your collected data in a specific format (.xlsx or .csv) before using the functions. Here’s an example of how to load and prepare your data using the readxl package:
FrequencyTable function will generates the frequency table from the collected length data by calculated optimum bin size or user defined bin size. It also allows the user to provide Lmax from reliable sources such as FishBase or empirical studies. The function extract the length frequency data from the frequency table with the upper length_range and allow users to save the frequency data as an excel file for further use in the FishPar function.
data: A numeric vector or data frame containing fish length measurements. If a data frame is provided, the first numeric column is used.
bin_width: Optional. A numeric value specifying the bin width for class intervals, if left NULL or if not provided, the bin width is automatically calculated using Wang et al. (2020) optimum bin size (OBS) formula formula.
Lmax: Optional. The maximum observed length of
fish. Required only if bin_width is NULL and Wang’s formula
is used. If not provided or left NULL then automatically calculate the
frequency table with the observed maximum length of the provided
data.
output_file: Optional. Character string specifying the output Excel file name. Defaults to “FrequencyTable_Output.xlsx”.
library(readxl)
# Load your length data from the system file
lenfreq_path <- system.file("exdata", "ExData.xlsx", package = "aLBI")
print(lenfreq_path) # Check the generated path
#> [1] "C:/Users/User/AppData/Local/Temp/Rtmpau2OPG/Rinst52c0638a9b3/aLBI/exdata/ExData.xlsx"
if (lenfreq_path == "") {
stop("The required file ExData.xlsx is missing. Please check the inst/extdata directory.")
}
# load the lenght frequency data
lenght_data <- readxl::read_excel(lenfreq_path)
print(lenght_data) # check the
#> # A tibble: 1,177 × 1
#> Length
#> <dbl>
#> 1 75
#> 2 66.7
#> 3 66
#> 4 64
#> 5 63.3
#> 6 63.2
#> 7 62.3
#> 8 62.2
#> 9 62
#> 10 61.3
#> # ℹ 1,167 more rows
# replace with your data directory# Running the FrequencyTable function
freqTable <- FrequencyTable(data = lenght_data, bin_width = NULL, Lmax = NULL, output_file = "FrequencyTable_Output.xlsx")
#> Lmax not provided. Using maximum observed length: 75
#> Calculated bin width using Wang's formula: 3
#> Warning: There was 1 warning in `dplyr::mutate()`.
#> ℹ In argument: `Length = as.numeric(sub(".*,(\\d+\\.?\\d*)[\\)\\]]?$", "\\1",
#> as.character(Length_Range)))`.
#> Caused by warning:
#> ! NAs introduced by coercion
#> Warning in FrequencyTable(data = lenght_data, bin_width = NULL, Lmax = NULL, :
#> Some Length values could not be extracted. Attempting fallback extraction.
# Viewing the results
freqTable$lfqTable # Display the frequency table
#> # A tibble: 21 × 2
#> Length_Range Frequency
#> <fct> <int>
#> 1 [9,12) 15
#> 2 [12,15) 63
#> 3 [15,18) 135
#> 4 [18,21) 137
#> 5 [21,24) 135
#> 6 [24,27) 156
#> 7 [27,30) 143
#> 8 [30,33) 80
#> 9 [33,36) 88
#> 10 [36,39) 67
#> # ℹ 11 more rows
freqTable$lfreq # Display the summarized frequencies with upper length ranges
#> # A tibble: 21 × 2
#> Length Frequency
#> <dbl> <int>
#> 1 12 15
#> 2 15 63
#> 3 18 135
#> 4 21 137
#> 5 24 135
#> 6 27 156
#> 7 30 143
#> 8 33 80
#> 9 36 88
#> 10 39 67
#> # ℹ 11 more rowsFreqTM Creates a frequency distribution table for fish length data across multiple months using a consistent length class structure. The bin width is determined by either a custom value or Wang’s formula, applied uniformly across all months. The function dynamically detects and renames columns to ‘Month’ and ‘Length’ from the input dataframe. The maximum observed length is included as part of the last class, with the upper bound set to the smallest multiple of the bin width greater than or equal to the maximum length. Months can be converted to dates using a configurable day and year, with dates assigned sequentially in ‘day.month.year’ format (e.g., 15.01.26).
data: A data frame containing columns for months and lengths (names can vary, e.g., ‘Month’, ‘Length’, or any other names).
bin_width: Optional. A numeric value specifying the bin width for class intervals, if left NULL or if not provided, the bin width is automatically calculated using Wang et al. (2020) optimum bin size (OBS) formula formula.
Lmax: Optional. The maximum observed length of
fish. Required only if bin_width is NULL and Wang’s formula
is used. If not provided or left NULL then automatically calculate the
frequency table with the observed maximum length of the provided
data.
date_config A list with elements
day (default 1) and year (default 2025) to set
the day and year for converting month names to dates. The day must be
between 1 and 31.
output_file: Optional. Character string specifying the output Excel file name. Defaults to “FreqTM_Output.xlsx”.
library(readxl)
# Load your length data from the system file
lenfreq_path <- system.file("exdata", "lenfreqM.xlsx", package = "aLBI")
print(lenfreq_path) # Check the generated path
#> [1] "C:/Users/User/AppData/Local/Temp/Rtmpau2OPG/Rinst52c0638a9b3/aLBI/exdata/lenfreqM.xlsx"
if (lenfreq_path == "") {
stop("The required file lenfreqM.xlsx is missing. Please check the inst/extdata directory.")
}
# load the length frequency data of multiple months
lenght_dataM <- readxl::read_excel(lenfreq_path)
print(lenght_dataM) # check the
#> # A tibble: 1,500 × 2
#> Months Length
#> <chr> <dbl>
#> 1 Jan 9.3
#> 2 Jan 11.5
#> 3 Jan 8.7
#> 4 Jan 7.4
#> 5 Jan 8.6
#> 6 Jan 9
#> 7 Jan 9.2
#> 8 Jan 8
#> 9 Jan 6.6
#> 10 Jan 9.5
#> # ℹ 1,490 more rows
# replace with your data directory# Running the FrequencyTable function
freqTableM <- FreqTM(data = lenght_dataM, bin_width = NULL, Lmax = NULL, output_file = "FreqTM.xlsx")
#> Data rows after NA removal: 1500
#> Renamed column 'Months' to 'Month'.
#> Renamed column 'Length' to 'Length'.
#> Min Length: 1.2, Max Length: 16
#> Lmax not provided. Using maximum observed length: 16
#> Calculated bin width using Wang's formula: 1
#> Length classes (upper bounds): 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
#> Converted months to dates: 01.01.25, 01.02.25, 01.03.25, 01.04.25, 01.05.25, 01.06.25, 01.07.25, 01.08.25
#> Rows in freq_complete for Jan (01.01.25): 15
#> Rows in freq_complete for Feb (01.02.25): 15
#> Rows in freq_complete for Mar (01.03.25): 15
#> Rows in freq_complete for Apr (01.04.25): 15
#> Rows in freq_complete for May (01.05.25): 15
#> Rows in freq_complete for Jun (01.06.25): 15
#> Rows in freq_complete for Jul (01.07.25): 15
#> Rows in freq_complete for Aug (01.08.25): 15
# Viewing the results
freqTableM
#> Length 01.01.25 01.02.25 01.03.25 01.04.25 01.05.25 01.06.25 01.07.25
#> 1 2 0 1 0 1 0 0 0
#> 2 3 0 0 0 0 0 0 0
#> 3 4 0 2 0 0 2 0 0
#> 4 5 0 22 10 1 3 7 6
#> 5 6 6 36 18 14 18 28 33
#> 6 7 22 35 23 20 22 34 36
#> 7 8 42 34 27 42 35 54 54
#> 8 9 34 21 29 36 36 29 27
#> 9 10 28 17 19 22 27 12 14
#> 10 11 16 1 16 18 22 6 10
#> 11 12 16 4 20 13 7 3 21
#> 12 13 6 1 8 6 2 1 13
#> 13 14 4 1 4 2 1 0 6
#> 14 15 1 0 0 0 0 1 1
#> 15 16 0 0 1 0 0 0 2
#> 01.08.25
#> 1 0
#> 2 2
#> 3 5
#> 4 39
#> 5 82
#> 6 51
#> 7 30
#> 8 13
#> 9 2
#> 10 3
#> 11 0
#> 12 0
#> 13 0
#> 14 0
#> 15 0The FishPar function estimates life history parameters (e.g., Lmax, Linf, Lmat, and Lopt) using Monte Carlo Simulation and Froese Sustainability Indicators using non-parametric bootstrapping method.
library(readxl)
# Load your length-frequency data from the system file
lenfreq_path <- system.file("exdata", "LC.xlsx", package = "aLBI")
print(lenfreq_path) # Check the generated path
#> [1] "C:/Users/User/AppData/Local/Temp/Rtmpau2OPG/Rinst52c0638a9b3/aLBI/exdata/LC.xlsx"
if (lenfreq_path == "") {
stop("The required file LC.xlsx is missing. Please check the inst/extdata directory.")
}
# load the lenght frequency data
lenfreq_data <- readxl::read_excel(lenfreq_path)
print(lenfreq_data) # check the data
#> # A tibble: 15 × 2
#> LengthClass Frequency
#> <dbl> <dbl>
#> 1 12 26
#> 2 15 166
#> 3 18 244
#> 4 21 582
#> 5 24 973
#> 6 27 1067
#> 7 30 963
#> 8 33 511
#> 9 36 472
#> 10 39 286
#> 11 42 173
#> 12 45 171
#> 13 48 83
#> 14 51 36
#> 15 54 36
# replace with your data directory# Running the FishPar function
results <- FishPar(data = lenfreq_data, resample = 1000, progress = FALSE, Linf = NULL, Linf_sd = 0.5, Lmat = NULL, Lmat_sd = 0.5)
# Viewing the results
results$estimated_length_par
#> Parameters Mean_estimate Lower_CI Upper_CI
#> Lmax_samples Lmax 54.00275 52.16610 55.95065
#> Linf_samples Linf 56.84500 54.91169 58.89542
#> Lmat_samples Lmat 31.41231 28.92748 33.75940
#> Lopt_samples Lopt 33.13341 29.70713 36.68036
#> Lopt_p10_samples Lopt_p10 36.44675 32.67785 40.34840
#> Lopt_m10_samples Lopt_m10 29.82007 26.73642 33.01233
results$estimated_froese_par
#> Parameters Mean_froese Lower_CI Upper_CI
#> 1 Pmat 17.873828 8.981777 39.02108
#> 2 Popt 23.195019 8.030254 50.58825
#> 3 Pmega 5.953396 1.620713 15.42085
results$forese_ind_vs_target
#> Parameters Froese_catch Froese_tar
#> 1 Pmat 17.873828 100
#> 2 Popt 23.195019 100
#> 3 Pmega 5.953396 20
results$Total_ind
#> [1] 5789
results$LM_ratio
#> Lmat_samples
#> 0.9480555
results$Pobj
#> [1] 47.02224The function returns a list with the following components saved in three different sheet of excel file:
The FishSS function evaluates stock status using criteria based on the estimated parameters by FishPar.
# Load the stock status criteria data
cpdata_path <- system.file("exdata", "cpdata.xlsx", package = "aLBI")
print(cpdata_path) #check if the path exist
#> [1] "C:/Users/User/AppData/Local/Temp/Rtmpau2OPG/Rinst52c0638a9b3/aLBI/exdata/cpdata.xlsx"
if (cpdata_path == "") {
stop("The required file cpdata.xlsx is missing. Please check the inst/extdata directory.")
}
# loading the cope and punt table
cpdata <- readxl::read_excel(cpdata_path)
print(cpdata)
#> # A tibble: 21 × 11
#> Tx A B C D E F G H I J
#> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 100 0 0 0 0 0 0 0 0 100 100
#> 2 95 0 0 0 0 22 0 11 0 100 93
#> 3 90 0 0 0 0 100 44 83 22 100 74
#> 4 85 0 0 0 0 100 100 100 67 100 63
#> 5 80 0 0 0 0 100 100 100 100 89 52
#> 6 75 0 0 0 0 100 100 100 100 74 37
#> 7 70 0 0 0 0 100 100 100 100 48 30
#> 8 65 0 0 0 0 100 100 100 100 33 22
#> 9 60 0 0 0 0 100 100 100 100 22 15
#> 10 55 0 0 0 0 100 100 100 100 11 7
#> # ℹ 11 more rows
# Running the FishSS function
stock_status <- FishSS(data = cpdata,
LM_ratio = results$LM_ratio,
Pmat = results$estimated_froese_par[1, 2],
Popt = results$estimated_froese_par[2, 2],
Pmega = results$estimated_froese_par[3,2]
)
# Viewing the stock status
stock_status
#> $StockStatus
#> TSB40 LSB25
#> 37 22
#>
#> $Selectivity
#> [1] "Fish small and optimally-sized or all but biggest"The function returns a named vector with TSB40 and LSB25 values indicating stock status, and selectivity of the fishing practice.
The LWR This function visualizes and models the relationship between length and weight (or any two continuous variables) using linear regression. It supports both standard and log-transformed models, producing a ggplot2-based plot with a fitted line, optional confidence interval shading, and annotations for the regression equation, R², and p-value. When save_output is TRUE, the plot and model summary are saved to the current working directory as a PDF and text file, respectively.
# Load the stock status criteria data
LWdata_path <- system.file("exdata", "LWdata.xlsx", package = "aLBI")
print(LWdata_path) #check if the path exist
#> [1] "C:/Users/User/AppData/Local/Temp/Rtmpau2OPG/Rinst52c0638a9b3/aLBI/exdata/LWdata.xlsx"
if (LWdata_path == "") {
stop("The required file LWdata.xlsx is missing. Please check the inst/extdata directory.")
}
# loading the cope and punt table
LWdata <- readxl::read_excel(LWdata_path)
print(LWdata)
#> # A tibble: 554 × 2
#> Length Weight
#> <dbl> <dbl>
#> 1 58.7 1025
#> 2 58.6 1013
#> 3 54.6 1011
#> 4 54.3 941
#> 5 54.2 946
#> 6 53 1120
#> 7 51.7 897
#> 8 51 1031
#> 9 50.5 882
#> 10 50.4 876
#> # ℹ 544 more rows
# Running the LWR function
lwr_result <- LWR(data = LWdata,
log_transform = TRUE,
point_col = "black",
line_col = "red",
shade_col = "red",
point_size = 2,
line_size = 1,
alpha = 0.2,
main = "Length-Weight Relationship",
xlab = NULL,
ylab = NULL,
save_output = TRUE)
#> Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
#> ℹ Please use `linewidth` instead.
#> ℹ The deprecated feature was likely used in the aLBI package.
#> Please report the issue at <https://github.com/Ataher76/aLBI/issues>.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
# Viewing the stock status
lwr_result
#> $model
#>
#> Call:
#> lm(formula = y ~ x)
#>
#> Coefficients:
#> (Intercept) x
#> -5.211 3.006
#>
#>
#> $intercept
#> (Intercept)
#> 0.0055
#>
#> $slope
#> x
#> 3.006
#>
#> $r_squared
#> [1] 0.9695
#>
#> $correlation_r
#> x
#> 0.9846
#>
#> $p_value
#> [1] 0
#>
#> $plotLength-Weight plot with model summery
The Fish Stock Assessment package provides a robust framework for estimating biological parameters and assessing fish stock status. By following the steps outlined in this vignette, you can effectively utilize this package for your fish stock assessment needs.
I would like to express my heartfelt gratitude to my supervisor, Dr. Mohammed Shahidul Alam, for his unwavering guidance, support, and encouragement. I am also sincerely thankful to the contributors and community members for their valuable feedback and support.
This vignette provides a comprehensive guide to using the Assessment package. By following these instructions, users can effectively conduct fish stock assessments and contribute to sustainable fishery management practices.
Readers are encouraged to read the article published in Fisheries
Research of this aLBI R Package to understand the
functionality and methodolgy.
Wang, K., Zhang, C., Xu, B., Xue, Y., & Ren, Y. (2020). Selecting optimal bin size to account for growth variability in Electronic LEngth Frequency ANalysis (ELEFAN). Fisheries Research, 225, 105474. https://doi.org/10.1016/j.fishres.2019.105474
Cope, J. M., & Punt, A. E. (2009). Length‐Based Reference Points for Data‐Limited Situations: Applications and Restrictions. Marine and Coastal Fisheries, 1(1), 169–186. https://doi.org/10.1577/C08-025.1
Froese, R. (2004). Keep it simple: Three indicators to deal with overfishing. Fish and Fisheries, 5(1), 86–91. https://doi.org/10.1111/j.1467-2979.2004.00144.x