--- title: "Mitscherlich-type response" author: Adrian Correndo & Austin Pearce output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Mitscherlich-type response} %\VignetteEncoding{UTF-8} %\VignetteEngine{knitr::rmarkdown} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width=6, fig.height=4 ) ``` ## Description This tutorial demonstrates the `mitscherlich()` function for fitting a continuous response model and estimating a critical soil test value. This function fits a Mitscherlich-type exponential regression model that follows a diminishing growth curve, and is sometimes also referred to as exponential "rise-to-the-max". Cerrato and Blackmer (1990) expressed it as: $$ y = a * (1-e^{-c(x + b)}) $$ where\ `a` = asymptote,\ `b` = model-fitting parameter ( $-b$ = X-intercept),\ `c` = curvature parameter. This exponential model is extensively used in agriculture to describe crops response to input since the biological meaning of its curved response. The `mitscherlich()` function works automatically with self-starting initial values to facilitate the model's convergence. The `mitscherlich()` function allows the user to control the number of parameters, effectively constraining the response curve if theoretically justified: 1. `type = 1, "no restriction", or "free"` (DEFAULT): three parameter model; $y = a * (1-e^{-c(x + b)})$ 2. `type = 2, "asymptote 100", or "100"`: two parameter model where asymptote = 100% RY; $y = 100 * (1-e^{-c(x + b)})$ 3. `type = 3, "asymptote 100 from 0", or "fixed":` one parameter model in which only the curvature varies and asymptote = 100 and model goes through origin; $y = 100 * (1-e^{-cx})$. Disadvantages this model might include: - lacks a parameter that can be directly interpreted as the critical soil test value - the model cannot be evaluated at the asymptote as CSTV would go to `Inf` - a fixed RY target for CSTV may be a somewhat arbitrary choice, but 95% is commonly used - model may not reach 95%, for which `NaN` results - there is no apparent confidence interval for the derived CSTV. For this latter purpose, we recommend the user to use the `boot_mitscherlich()` function for a reliable confidence interval estimation of parameters and CSTV via bootstrapping (resampling with replacement). ## General Instructions 1. Load your dataframe with soil test value (stv) and relative yield (ry) data. 2. Specify the following arguments into the function `mitscherlich()`: 1. `type` select the type of parameterization of the model (`type = 1, 2, or 3; see above`) 2. `data` (optional) 3. `stv` (soil test value) and `ry` (relative yield) columns or vectors, 4. `target` (default = 95) to calculate the STV at a specific `ry` target. 5. `tidy` TRUE-default- (produces a data.frame with results) or FALSE (store results as list) 6. `plot` TRUE (produces a ggplot as main output) or FALSE (no plot, only results as data.frame) 7. `resid` TRUE (produces plots with residuals analysis) or FALSE (no plot) 3. Run and check results. 4. Check residuals plot, and warnings related to potential limitations of this model. 5. Adjust curve plots as desired. # Tutorial ```{r setup} library(soiltestcorr) ``` Suggested packages ```{r warning=FALSE, message=FALSE} # Install if needed library(ggplot2) # Plots library(dplyr) # Data wrangling library(tidyr) # Data wrangling library(purrr) # Mapping ``` ## Load datasets ```{r} # Native fake dataset from soiltestcorr package corr_df <- soiltestcorr::data_test ``` # Fit `mitscherlich()` ## 1. Individual fits ### 1.1. Different number of parameters `type = #` ```{r warning=TRUE, message=TRUE} # Type = 1, no restriction (3 parameters) mitscherlich(corr_df, STV, RY, type = 1) # Type = 2, fixed asymptote value at 100 (2 parameters) mitscherlich(corr_df, STV, RY, type = 2) # Type = 3, fixed origin at 0 and asymptote at 100 (1 parameters) mitscherlich(corr_df, STV, RY, type = 3) ``` ### 1.2. `tidy` = FALSE It returns a LIST (may more efficient for multiple fits at once) ```{r warning=TRUE, message=TRUE} # Using dataframe argument, tidy = FALSE -> return a LIST mitscherlich(data = corr_df, STV, RY, target = 90, tidy = FALSE) ``` ### 1.3. Alternative using the data frame vectors You can call `stv` and `ry` vectors using the `$`. The `tidy` argument still applies for controlling the output type. ```{r warning=TRUE, message=TRUE} fit_vectors_list <-mitscherlich(stv = corr_df$STV, ry = corr_df$RY, tidy = FALSE) fit_vectors_tidy <-mitscherlich(stv = corr_df$STV, ry = corr_df$RY, tidy = TRUE) ``` ## 2. Multiple fits at once ```{r warning=T, message=F} # Example 1. Fake dataset manually created data_1 <- data.frame("RY" = c(65,80,85,88,90,94,93,96,97,95,98,100,99,99,100), "STV" = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)) # Example 2. Native fake dataset from soiltestcorr package data_2 <- soiltestcorr::data_test # Example 3. Native dataset from soiltestcorr package, Freitas et al. (1966), used by Cate & Nelson (1971) data_3 <- soiltestcorr::freitas1966 %>% rename(STV = STK) data.all <- bind_rows(data_1, data_2, data_3, .id = "id") ``` Note: the `stv` column needs to have the same name for all datasets if binding rows. ### 2.1. Using `map()` ```{r warning=T, message=F} # Run multiple examples at once with map() data.all %>% nest(data = c("STV", "RY")) %>% mutate(model = map(data, ~ mitscherlich(stv = .$STV, ry = .$RY))) %>% unnest(model) ``` ### 2.2. Using `group_modify()` Alternatively, with `group_modify()`, nested data is not required. However, it still requires a grouping variable (in this case, `id`) to identify each dataset. `group_map()` may also be used, though `list_rbind()` is required to return a tidy data frame of the model results instead of a list. ```{r warning=T, message=F} data.all %>% group_by(id) %>% group_modify(~ soiltestcorr::mitscherlich(data = ., STV, RY)) ``` ## 3. Bootstrapping A suitable alternative for obtaining confidence intervals for parameters or derived quantities is bootstrapping. Bootstrapping is a resampling technique (with replacement) that draws samples from the original data with the same size. If you have groups within your data, you can specify grouping variables as arguments in order to maintain, within each resample, the same proportion of observations than in the original dataset. This function returns a table with as many rows as the resampling size (n) containing the results for each resample. ```{r} set.seed(123) boot_mits <- boot_mitscherlich(corr_df, STV, RY, target = 90, n = 200) boot_mits %>% head(n = 5) # CSTV Confidence Interval quantile(boot_mits$CSTV, probs = c(0.025, 0.5, 0.975), na.rm = TRUE) # Plot boot_mits %>% ggplot2::ggplot(aes(x = CSTV))+ geom_histogram(color = "grey25", fill = "#9de0bf", bins = 10) ``` ## 4. Plots ### 4.1. Calibration Curve We can generate a ggplot with the same `mitscherlich()` function. We just need to specify the argument `plot = TRUE`. ```{r warning=F, message=F} data_3 <- soiltestcorr::freitas1966 plot_mit <- mitscherlich(data_3, STK, RY, plot = TRUE) plot_mit ``` ### 4.2 Fine-tune the plots As ggplot object, plots can be adjusted in several ways, such as modifying titles and axis scales. ```{r warning=F, message=F} plot_mit + # Main title ggtitle("My own plot title")+ # Axis titles labs(x = "Soil Test K (ppm)", y = "Cotton RY(%)") + # Axis scales scale_x_continuous(limits = c(20,220), breaks = seq(0,220, by = 10)) ``` ### 4.3. Residuals Set the argument `resid = TRUE`. ```{r warning=F, message=F} # Residuals plot mitscherlich(data_3, STK, RY, resid = TRUE) ``` #### References *Cerrato, M. E., & Blackmer, A. M. (1990). Comparison of models for describing corn yield response to nitrogen fertilizer. Agronomy Journal, 82(1), 138--143. * *Melsted, S.W. and Peck, T.R. (1977). The Mitscherlich-Bray Growth Function. In Soil Testing (eds T. Peck, J. Cope and D. Whitney). 10.2134/asaspecpub29.c1*