aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnil Tellbuescher <anil@tellbuescher.online>2024-11-16 13:34:09 +0100
committerAnil Tellbuescher <anil@tellbuescher.online>2024-11-16 13:34:09 +0100
commit818de681ddacdf3be06fd292f965a3cca858118e (patch)
treefe4bd85e7f7904d86cb80948f8279b365b5a2477
parentd202b127909669c484bc74bb87d629f9e3bea299 (diff)
add linearity tests for calibration data
-rw-r--r--R/linearity.R113
1 files changed, 113 insertions, 0 deletions
diff --git a/R/linearity.R b/R/linearity.R
new file mode 100644
index 0000000..6230d04
--- /dev/null
+++ b/R/linearity.R
@@ -0,0 +1,113 @@
+#' Assess the linearity of a calibration curve
+#'
+#' A function to create diagnostic plots for the assessment of the linearity of
+#' calibration data based on their point-to-point slope or the curvature.
+#' The underlying methods follow ISO 84 66-1:2021 and DIN 32 402-51:2017
+#' (German Industrial Norm).
+#'
+#' The point-to-point slope method is based on the assumption that the slope
+#' between two points should not vary greatly within the linear range.
+#'
+#' The curvature method is similar to the point-to-point slope method. Here,
+#' the ratio between the instrument signal and the concentration of the
+#' calibration standard is assumed not to vary greatly within the linear range.
+#'
+#' The use of the Mandel test is discouraged due to its limitations in the
+#' identification of non-linear behaviour of calibration courves (Andrade and
+#' Gomes-Carracedo, 2013).
+#'
+#' @param x numeric vector of independent values (usually concentrations).
+#' @param y numeric vector of dependent values (usually the signal of the
+#' analytical device).
+#' @param method character string. Supported methods are "slope" and
+#' "curvature".
+#' @param tolerance numeric value describing the acceptable deviation from the
+#' median of the slopes or the signal-to-concentration ratio. The default
+#' tolerance is 10%.
+#' @return returns a diagnostic plot
+#'
+#' @author Anil Axel Tellbüscher
+#'
+#' @importFrom graphics abline
+#' @importFrom stats median
+#'
+#' @examples
+#' # Point-to-point slope plot
+#' linearity(din32645$x, din32645$y, method = "slope")
+#'
+#' # Curvature plot
+#' linearity(din32645$x, din32645$y, method = "curvature", tolerance = 0.2)
+#'
+#' @references ISO 8466-1:2021. Water quality — Calibration and evaluation of
+#' analytical methods — Part 1: Linear calibration function
+#'
+#' J. M. Andrade and M. P. Gomez-Carracedo (2013) Notes on the use of
+#' Mandel's test to check for nonlinearity in laboratory calibrations.
+#' Analytical Methods 5(5), 1145 - 1149.
+#'
+#' @export
+# Function to assess linearity of data using either slope or curvature method
+linearity <- function(x, y, method = NULL, tolerance = 0.1) {
+
+ # Check data integrity
+ # Ensure that x and y vectors have the same length
+ stopifnot("x and y must have the same length!" = length(x) == length(y))
+
+ # Ensure that a method has been specified
+ stopifnot("Method must be defined!\n
+ Select either 'slope' for the point-to-point slope or 'curvature'
+ for the empirical curvature test" =
+ !is.null(method))
+
+ # Validate that the method is either 'slope' or 'curvature'
+ stopifnot("Invalid input!\n
+ Select either 'slope' for the point-to-point slope or 'curvature'
+ for the empirical curvature test" =
+ method %in% c("slope", "curvature"))
+
+ # Calculate the 'result' based on the chosen method
+ if (method == "slope") {
+ # For the 'slope' method, calculate the difference between consecutive points
+ x_diff = diff(x) # Difference in x values
+ y_diff = diff(y) # Difference in y values
+ result = y_diff / x_diff # Point-to-point slope (rate of change)
+ } else if (method == "curvature") {
+ # For the 'curvature' method, calculate the signal-to-concentration ratio
+ result = y / x # Element-wise division of y by x
+ }
+
+ # Calculate the median of the results for tolerance check
+ result_median <- median(result)
+
+ # Define upper and lower tolerance boundaries
+ upper_tolerance <- result_median + tolerance * result_median
+ lower_tolerance <- result_median - tolerance * result_median
+
+ # Create a data frame to store the result and corresponding indices
+ df <- data.frame(result = result, index = 1:length(result))
+
+ # Identify points that fall outside the tolerance range
+ outside_tolerance <- rbind(
+ subset(df, result > upper_tolerance), # Points above the upper tolerance
+ subset(df, result < lower_tolerance) # Points below the lower tolerance
+ )
+
+ # Basic scatter plot of the result against the index
+ plot(result ~ index, data = df,
+ main = "linearity assessment", ylab = method,
+ pch = 16)
+
+ # Draw a line connecting all the points to visualize the trend
+ lines(df$index, df$result, col = "blue") # Blue line connecting points
+
+ # Highlight points that are outside the tolerance range in red
+ points(x = outside_tolerance$index, y = outside_tolerance$result,
+ pch = 16, col = "red")
+
+ # Add a horizontal line at the median value of the result
+ abline(h = result_median, col = "red")
+
+ # Add dashed horizontal lines at the upper and lower tolerance limits
+ abline(h = upper_tolerance, col = "red", lty = 3) # Upper tolerance
+ abline(h = lower_tolerance, col = "red", lty = 3) # Lower tolerance
+}

Contact - Imprint