This tutorial is intended to show how to deploy the linear_plateau()
function for estimating a continuous response model with a critical soil
test value. This function fits the classical regression response model
that follows two phases: i) a first linear phase described as y = b0 +
b1 x, and ii) a second phase were the RY response to increasing STV
becomes NULL (flat), described as plateau = y = b0 + b1 Xc, where Xc
represents the CSTV. The function works automatically with self starting
initial values to facilitate the model’s convergence. This approach is
one of the regression models with simple interpretation of its
parameters. Some disadvantages are that: i) the user does not have
control to estimate the critical value (the model parameter) for an
specific ry level; and ii) the confidence interval of the critical level
is generally unreliable. We recommend the user to use a re-sampling
technique (e.g. bootstrapping) for a more reliable confidence interval
estimation for parameters and CSTV
Load your dataframe with soil test value (stv) and relative yield
(ry) data.
Specify the following arguments into the function
-linear_plateau()-:
(a). data
(optional),
(b). stv
(soil test value) and ry
(relative
yield) columns or vectors,
(c). target
(optional) if want a CSTV for a different
`ry`` than the plateau.
(d). tidy
TRUE (produces a data.frame with results) or
FALSE (store results as list),
(e). plot
TRUE (produces a ggplot as main output) or
FALSE (no plot, only results as data.frame),
(f). resid
TRUE (produces plots with residuals analysis)
or FALSE (no plot),
Run and check results.
Check residuals plot, and warnings related to potential
limitations of this model.
Adjust curve plots as desired.
library(soiltestcorr)
Suggested packages
# Install if needed
library(ggplot2) # Plots
library(dplyr) # Data wrangling
library(tidyr) # Data wrangling
library(utils) # Data wrangling
library(data.table) # Mapping
library(purrr) # Mapping
This is a basic example using three different datasets:
# Example 1 dataset
# Fake dataset manually created
<- data.frame("RY" = c(65,80,85,88,90,94,93,96,97,95,98,100,99,99,100),
data_1 "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
<- soiltestcorr::data_test
data_2
# Example 3. Native dataset from soiltestcorr package, Freitas et al. (1966), used by Cate & Nelson (1971)
<- soiltestcorr::freitas1966 data_3
RY target = 90%, confidence level = 0.95, replace with your desired
values
tidy
= FALSE It returns a LIST (more efficient for multiple fits at once)
# Using dataframe argument, tidy = FALSE -> return a LIST
<-
fit_1_tidy_false ::linear_plateau(data = data_1,
soiltestcorrry = RY,
stv = STV,
tidy = FALSE)
::head(fit_1_tidy_false)
utils#> $intercept
#> [1] 65.87
#>
#> $slope
#> [1] 5.09
#>
#> $equation
#> [1] "65.9 + 5.09x if x<CSTV"
#>
#> $plateau
#> [1] 97.4
#>
#> $target
#> [1] 97.4
#>
#> $CSTV
#> [1] 6.2
tidy
= TRUE It returns a data.frame (more organized results)
# Using dataframe argument, tidy = FALSE -> return a LIST
<-
fit_1_tidy_true ::linear_plateau(data = data_1,
soiltestcorrry = RY,
stv = STV,
tidy = TRUE)
fit_1_tidy_true#> intercept slope equation plateau target CSTV LL_cxp UL_cxp
#> 1 65.87 5.09 65.9 + 5.09x if x<CSTV 97.4 97.4 6.2 5.1 7.4
#> CI_type AIC AICc R2
#> 1 Wald Conf. Interval 82 86 0.9
You can call stv
and ry
vectors using the
$
.
The tidy
argument still applies for controlling the
output type
<-
fit_1_vectors_list ::linear_plateau(ry = data_1$RY,
soiltestcorrstv = data_1$STV,
tidy = FALSE)
<-
fit_1_vectors_tidy ::linear_plateau(ry = data_1$RY,
soiltestcorrstv = data_1$STV,
tidy = TRUE)
<-
fit_2 ::linear_plateau(data = data_2,
soiltestcorrry = RY,
stv = STV)
::head(fit_2)
utils#> $intercept
#> [1] 53.72
#>
#> $slope
#> [1] 1.55
#>
#> $equation
#> [1] "53.7 + 1.55x if x<CSTV"
#>
#> $plateau
#> [1] 96.2
#>
#> $target
#> [1] 96.2
#>
#> $CSTV
#> [1] 27.4
<-
fit_3 ::linear_plateau(data = data_3,
soiltestcorrry = RY,
stv = STK)
::head(fit_3)
utils#> $intercept
#> [1] 39.24
#>
#> $slope
#> [1] 0.75
#>
#> $equation
#> [1] "39.2 + 0.75x if x<CSTV"
#>
#> $plateau
#> [1] 95.6
#>
#> $target
#> [1] 95.6
#>
#> $CSTV
#> [1] 75
Note: the stv
column needs to have the same name for
all datasets
#
<- dplyr::bind_rows(data_1, data_2,
data.all %>% dplyr::rename(STV = STK),
data_3 .id = "id") %>%
::nest(data = c("STV", "RY")) tidyr
# Run multiple examples at once with map()
<-
fit_multiple_map %>%
data.all mutate(linear_plateau = purrr::map(data,
~ soiltestcorr::linear_plateau(ry = .$RY,
stv = .$STV,
tidy = TRUE)))
::head(fit_multiple_map)
utils#> # A tibble: 3 x 3
#> id data linear_plateau
#> <chr> <list> <list>
#> 1 1 <tibble [15 x 2]> <df [1 x 12]>
#> 2 2 <tibble [137 x 2]> <df [1 x 12]>
#> 3 3 <tibble [24 x 2]> <df [1 x 12]>
Alternatively, with group_map, we do not require nested data.
However, it requires to dplyr::bind_rows and add an id
column specifying the name of each dataset.
This option return models as lists objects.
<-
fit_multiple_group_map ::bind_rows(data_1, data_2, .id = "id") %>%
dplyr::group_by(id) %>%
dplyr::group_map(~ soiltestcorr::linear_plateau(data = .,
dplyrry = RY,
stv = STV,
tidy = TRUE))
::head(fit_multiple_group_map)
utils#> [[1]]
#> intercept slope equation plateau target CSTV LL_cxp UL_cxp
#> 1 65.87 5.09 65.9 + 5.09x if x<CSTV 97.4 97.4 6.2 5.1 7.4
#> CI_type AIC AICc R2
#> 1 Wald Conf. Interval 82 86 0.9
#>
#> [[2]]
#> intercept slope equation plateau target CSTV LL_cxp UL_cxp
#> 1 53.72 1.55 53.7 + 1.55x if x<CSTV 96.2 96.2 27.4 24 30.7
#> CI_type AIC AICc R2
#> 1 Wald Conf. Interval 1026 1026 0.52
We can generate a ggplot with the same linear_plateau() function.
We just need to specify the argument plot = TRUE
.
<-
linear_plateau_plot ::linear_plateau(data = data_3,
soiltestcorrry = RY,
stv = STK,
plot = TRUE)
linear_plateau_plot
### 3.1.2 Fine-tune the plots
As ggplot object, plots can be adjusted in several ways.
For example, modifying titles
<-
linear_plateau_plot_2 +
linear_plateau_plot # Main title
ggtitle("My own plot title")+
# Axis titles
labs(x = "Soil Test K (ppm)",
y = "Cotton RY(%)")
linear_plateau_plot_2
Or modifying axis scales
<-
linear_plateau_plot_3 +
linear_plateau_plot_2 # Axis scales
scale_x_continuous(limits = c(20,220),
breaks = seq(0,220, by = 20))+
# Axis limits
scale_y_continuous(limits = c(30,100),
breaks = seq(30,100, by = 10))
linear_plateau_plot_3
We can generate a plot with the same linear_plateau() function.
We just need to specify the argument resid
= TRUE`.
# Residuals plot
::linear_plateau(data = data_3,
soiltestcorrry = RY,
stv = STK,
resid = TRUE)
#> $intercept
#> [1] 39.24
#>
#> $slope
#> [1] 0.75
#>
#> $equation
#> [1] "39.2 + 0.75x if x<CSTV"
#>
#> $plateau
#> [1] 95.6
#>
#> $target
#> [1] 95.6
#>
#> $CSTV
#> [1] 75
#>
#> $LL_cxp
#> [1] 46.4
#>
#> $UL_cxp
#> [1] 103.6
#>
#> $CI_type
#> [1] "Wald Conf. Interval"
#>
#> $AIC
#> [1] 188
#>
#> $AICc
#> [1] 190
#>
#> $R2
#> [1] 0.66
References
Anderson, R. L., and Nelson, L. A. (1975). A Family of Models
Involving Intersecting Straight Lines and Concomitant Experimental
Designs Useful in Evaluating Response to Fertilizer Nutrients.
Biometrics, 31(2), 303–318. 10.2307/2529422