cndplantanalysis is an R package
designed for Compositional Nutrient Diagnosis (CND) of
plant tissue tests. CND translates constrained leaf nutrient
concentrations into unconstrained, scale-invariant row-centered log
ratios within a \(d\)-dimensional
multinomial simplex (\(S^d\)).
The package provides an end-to-end, reproducible workflow for: 1.
Transforming raw nutrient concentrations into row-centered log ratios
(\(V_X\)) and filling values (\(R_d\)). 2. Conducting iterative database
partitioning via the Cate–Nelson procedure. 3. Fitting cubic polynomial
regression models to cumulative variance functions \(F_i^C(V_X)\) to establish objective,
non-arbitrary yield cutoffs at inflection points (\(-b / 3a\)). 4. Deriving theoretical
critical nutrient imbalance thresholds (\(r^2\)) mapped from the cumulative
chi-square distribution with \(d + 1\)
degrees of freedom. 5. Standardizing independent tissue samples against
high-yield (hyp) reference norms to calculate individual
nutrient indices (\(I_X\)) and the
global nutrient imbalance index (\(r^2\)). 6. Performing automated empirical
Cate–Nelson ANOVA grid search and generating publication-ready
ggplot2 diagnostic plots.
The statistical and agronomic methodology implemented in
cndplantanalysis is grounded in foundational CND
literature:
You can install the development version of
cndplantanalysis from CRAN:
install.packages("cndplantanalysis")| Function Name | Description |
|---|---|
simplex_table() |
Sorts database by yield, calculates residual filling value (\(R_d = 100 - \sum \text{Nutrients}\)), and computes geometric mean (\(G\)). |
log_centered_table() |
Computes scale-invariant row-centered log ratios (\(V_X = \ln(X / G)\)). |
iteration_for_hyp() |
Iteratively partitions database across \(n - 3\) steps to calculate variance ratios \(f_i(V_X)\) and cumulative ratios \(F_i^C(V_X)\). |
cut_off_table() |
Fits cubic polynomial models \(aY^3 + bY^2 + cY + d\), determines
inflection point yield cutoffs (\(-b /
3a\)), and extracts high-yield (hyp) norms. |
plot_cnd_chisq() |
Plots the upper-tail cumulative chi-square distribution curve (\(df = d + 1\)) and marks theoretical critical \(r^2\) threshold. |
diagnose_specimen() |
Standardizes new crop samples against
hyp norms to calculate individual CND nutrient indices
(\(I_X\)) and global imbalance index
(\(r^2\)). |
calc_cate_nelson_empirical() |
Evaluates candidate split pairs via ANOVA grid search to maximize \(SS_{\text{between}}\) for automated Cate–Nelson thresholding. |
plot_cate_nelson() |
Generates a publication-ready
ggplot2 quadrant scatter plot (Yield vs. \(r^2\)) with automated or specified
Cate–Nelson threshold lines. |
plot_cumulative_variance() |
Generates a connected scatter plot
(ggplot2) of \(F_i^C(V_X)\) vs. Yield for an individual
nutrient or all nutrients simultaneously. |
plot_cnd_yield_nlr() |
Fits a non-linear polynomial regression
(ggplot2) relating crop yield to CND imbalance index (\(r^2\)) with yield extrapolation. |
plot_cnd_yield_linear() |
Fits a linear regression model
(ggplot2) relating crop yield to o CND imbalance index
(\(r^2\)) with yield
extrapolation. |
This example demonstrates a complete step-by-step CND analysis using survey and validation data (e.g., sweet corn survey dataset from Khiari et al., 2001):
library(cndplantanalysis)
library(ggplot2)
# ==============================================================================
# Step 1: Prepare Survey Data & Calculate Simplex Values (Rd and G)
# ==============================================================================
# Sample dataset with Yield and nutrient concentrations (N, P)
survey_data <- data.frame(
Sample = paste0("S", 1:40),
Yield = c(12.93, 10.32, 8.65, 8.34, 8.21, 8.14, 8.10, 8.09, 7.93, 7.93,
6.94, 6.94, 6.72, 6.56, 5.76, 5.75, 5.60, 5.60, 5.51, 5.48,
5.31, 5.31, 5.16, 5.16, 4.96, 4.92, 4.76, 4.76, 4.46, 4.46,
3.97, 3.97, 3.94, 3.89, 2.78, 2.38, 1.99, 1.99, 1.19, 1.14),
N = c(3.52, 4.20, 3.82, 3.55, 4.36, 4.09, 3.79, 4.48, 4.48, 3.97,
4.47, 3.29, 4.19, 4.26, 3.72, 4.47, 3.96, 3.51, 3.48, 3.89,
4.17, 3.86, 4.70, 4.07, 4.38, 3.79, 4.00, 4.09, 3.97, 3.92,
3.96, 5.05, 2.66, 3.89, 4.49, 4.54, 4.69, 4.42, 4.11, 3.03),
P = c(0.35, 0.37, 0.65, 0.42, 0.42, 0.39, 0.48, 0.43, 0.41, 0.36,
0.33, 0.25, 0.35, 0.80, 0.32, 0.49, 0.34, 0.31, 0.30, 0.48,
0.38, 0.38, 0.41, 0.38, 0.43, 0.33, 0.41, 0.33, 0.46, 0.44,
0.43, 0.60, 0.44, 0.29, 0.47, 0.41, 0.39, 0.41, 0.35, 0.42)
)
simplex_res <- simplex_table(
data = survey_data,
sample_col = "Sample",
yield_col = "Yield",
nutrient_cols = c("N", "P")
)
# ==============================================================================
# Step 2: Compute Row-Centered Log Ratios (Vx)
# ==============================================================================
lc_res <- log_centered_table(
simplex_data = simplex_res,
sample_col = "Sample",
yield_col = "Yield",
nutrient_cols = c("N", "P")
)
# ==============================================================================
# Step 3: Iterative Partitioning & Cumulative Variance Ratios
# ==============================================================================
iter_res <- iteration_for_hyp(
lc_data = lc_res,
yield_col = "Yield",
nutrient_cols = c("N", "P"),
digits = 2
)
# ==============================================================================
# Step 4: Fit Cubic Models & Extract CND Reference Norms
# ==============================================================================
cnd_out <- cut_off_table(
iter_data = iter_res,
lc_data = lc_res,
yield_col = "Yield",
nutrient_cols = c("N", "P"),
digits = 2
)
# View High-Yield CND Norms
print(cnd_out$norms_table)
# ==============================================================================
# Step 5: Diagnose New/Validation Specimens
# ==============================================================================
validation_data <- data.frame(
Sample = c("V1", "V2", "V3", "V11"),
Yield = c(4.97, 8.34, 3.06, 5.25),
N = c(3.51, 3.76, 4.09, 2.81),
P = c(0.30, 0.38, 0.65, 0.28)
)
diag_results <- diagnose_specimen(
new_data = validation_data,
norms_table = cnd_out$norms_table,
sample_col = "Sample",
yield_col = "Yield",
nutrient_cols = c("N", "P"),
digits = 2
)
print(diag_results)
# ==============================================================================
# Step 6: Visualizations & Cate–Nelson Partitioning
# ==============================================================================
# A. Cumulative Variance Curve
p1 <- plot_cumulative_variance(iter_res, lc_res, nutrient = "all")
# B. Chi-Square Distribution Threshold
p2 <- plot_cnd_chisq(nutrient_cols = c("N", "P"), low_yield_pct = 67.5)
# C. Cate–Nelson Quadrant Scatter Plot
p3 <- plot_cate_nelson(diag_results, crit_r2 = 1.4, crit_yield = 6.40)
# D. Non-Linear Yield vs. r^2 Response
p4 <- plot_cnd_yield_nlr(
data = diag_results,
r2_col = "r2",
yield_col = "Yield",
critical_r2 = 1.4,
plot_title = "Yield vs CND Nutrient Imbalance Index (r²)"
)This package is licensed under the GPL-3 License.