This Computational Provenance Record documents the statistical computing environment, software dependencies, computational provenance, and bibliographic references associated with the RAISINS Pooled Analysis - Two-Factor RBD module (a two-factor factorial experiment laid out in a Randomized Block Design and pooled across several locations, seasons or years). It is intended to support computational reproducibility and software transparency. Detailed statistical methodology, mathematical derivations, and user guidance are provided separately in the official module tutorial.
Any issues or updates required please comment here
Note : the pooling-model F-test logic, the Aitken transformation and the summary-statistic assembly are implemented by the RAISINS team.
4 Default Methods & Parameters
Analysis
Step / Parameter
Default Method / Value
Input &
Design
Input structure
One column identifying the Location / Season / Year, one column for Factor A, one for Factor B, one column for the Block (replication) within each location, followed by one column per trait; all traits are analysed in a single run
Design
Two-factor factorial in a Randomized Block Design (RBD), repeated over several environments and analysed jointly (pooled)
Interaction columns
The A×B, A×L, B×L and A×B×L combination labels are formed internally from the Factor and Location columns
Homogeneity
& Transformation
Bartlett test
For each trait, a separate aov(Y ~ Block + FactorA + FactorB) is fitted within every location (each location must have ≥ 2 blocks and ≥ 2 levels of each factor) and bartlett.test() is applied to the list of fitted models to test equality of the per-location error variances
Aitken transformation
Applied automatically to a trait only when its Bartlett test is significant (p ≤ 0.05): each observation is divided by the square root of its own location's error mean square (√MSEloc). Traits with homogeneous variances are left untransformed
Pooled
ANOVA
Model
lm(Y ~ L + L:Block + A + B + A:B + L:A + L:B + L:A:B) with sums of squares from car::Anova(type = "II"); sources are Location, Factor A, Factor B, Replication within Location (L×Block), A×B, L×A, L×B, L×A×B and Pooled Error
Mean squares
Each mean square is SS / df; the Pooled Error mean square is the residual of the fitted model
Pooling Model
(F-test error terms)
Model 1 - A, B, Location all Random
Location, Factor A and Factor B are each tested against the L×A×B mean square; the interactions are tested against the Pooled Error
Model 2 - Factors Fixed, Location Random
Location is tested against the Pooled Error; Factor A and Factor B are tested against the L×A×B mean square
Model 3 - Location Fixed, Factors Random
Location is tested against the L×A×B mean square; Factor A and Factor B are tested against the Pooled Error
Model 4 - A, B, Location all Fixed (default)
Every source, including Location, Factor A and Factor B, is tested against the Pooled Error mean square
Significance
& Rounding
Level (α)
0.05 (default) or 0.01
Star codes & rounding
**p ≤ 0.01, * 0.01 < p ≤ 0.05, NS otherwise; results rounded to 2 decimal places by default
Mean
Comparison
Method
LSD (default) via agricolae::LSD.test(), TUKEY via agricolae::HSD.test(), or DMRT via agricolae::duncan.test(); each is supplied the error degrees of freedom and mean square that match the selected pooling model for that source
P-value adjustment
Offered for LSD only, and passed straight through to the p.adj argument of agricolae::LSD.test(): none (default), bonferroni (FWER), holm (Holm–Bonferroni, FWER) or BH (Benjamini–Hochberg, FDR). TUKEY and DMRT carry their own multiplicity control and take no adjustment argument
Letter grouping
Compact-letter groupings are produced for a source only when its level count is within the display limit and letter grouping is enabled; groups are ordered with gtools::mixedsort()
Summary
Statistics
SEm, SEd
SE(mean) = √(MSE / r) and SE(difference) = √(2 · MSE / r), where r is the number of observations behind each mean of the source (from the LSD.test() means table) and MSE is the model-matched error mean square
CV, CD
The coefficient of variation and the critical difference are taken from the agricolae test statistics for each source at the chosen α
5 R Code for Key Analytical Steps
The steps below reproduce the module’s engine on a self-contained copy of the demo dataset dataset1.csv - a two-factor RBD (Factor A: S1, S2; Factor B: C1, C2) grown at two locations (A, B) with four blocks per location, and the trait Yield. The data are built inline below so this record runs on its own, without any external file; in the app the same columns are read from the user’s uploaded CSV, and the analysis loop runs over every trait column (Yield, Char1…Char6).
For any issues in the workflow please comment here.
5.1 Worked Example: Input Data
# Self-contained copy of dataset1 (Location x FactorA x FactorB x Block, balanced).# In the app these columns come from the user's uploaded CSV.data <-data.frame(Location =rep(c("A", "B"), each =16),FactorA =rep(rep(c("S1", "S2"), each =8), times =2),FactorB =rep(rep(c("C1", "C2"), each =4), times =4),Block =rep(1:4, times =8),Yield =c(1.35, 1.27, 0.93, 1.04, 1.39, 0.63, 0.78, 1.23,1.13, 1.64, 0.85, 0.68, 1.87, 0.88, 0.87, 0.83,1.67, 1.13, 1.31, 1.03, 1.43, 1.22, 1.02, 0.90,1.06, 0.77, 1.11, 1.29, 1.30, 0.83, 0.87, 0.91),stringsAsFactors =FALSE)data$Location <-as.factor(data$Location) # A, B (2 environments)data$FactorA <-as.factor(data$FactorA) # S1, S2data$FactorB <-as.factor(data$FactorB) # C1, C2data$Block <-as.factor(data$Block) # 1..4 (blocks within each location)trait <-"Yield"# analysis is repeated for every trait# combination labels used by the interaction sources and mean comparisonsdata$AxB <-interaction(data$FactorA, data$FactorB, sep ="x")data$AxL <-interaction(data$FactorA, data$Location, sep ="x")data$BxL <-interaction(data$FactorB, data$Location, sep ="x")data$AxBxL <-interaction(data$FactorA, data$FactorB, data$Location, sep ="x")
5.2 Homogeneity of Error Variances (Bartlett) and Aitken Transformation
Before pooling, the error variances of the individual locations are compared. Each within-location model is a block-design ANOVA (Y ~ Block + FactorA + FactorB). A significant Bartlett test flags heterogeneity, and the trait is Aitken-transformed by dividing each observation by the square root of its own location’s error mean square.
# one within-location RBD ANOVA per environment -> list of fitted modelsmodels_by_loc <-lapply(split(data, data$Location), function(sub) { sub <-droplevels(sub)if (nlevels(factor(sub$Block)) <2||nlevels(factor(sub$FactorA)) <2||nlevels(factor(sub$FactorB)) <2) return(NULL)aov(as.formula(paste(trait, "~ Block + FactorA + FactorB")), data = sub)})models_by_loc <-Filter(Negate(is.null), models_by_loc)# Bartlett test across the per-location residualsbt <-bartlett.test(models_by_loc)bt$statistic # chi-squarebt$p.value # significance of variance heterogeneity# per-location error mean squaremse_by_loc <-sapply(models_by_loc, function(m) sum(resid(m)^2) /df.residual(m))# Aitken transform ONLY when Bartlett is significant (p <= 0.05)data_t <- dataif (bt$p.value <=0.05) {for (loc innames(mse_by_loc)) { rows <- data$Location == loc data_t[rows, trait] <- data[rows, trait] /sqrt(mse_by_loc[loc]) }}# data_t holds the (possibly transformed) response used in the pooled ANOVA
5.3 Pooled Factorial RBD ANOVA
The pooled model is fitted on the (possibly transformed) response, and Type II sums of squares are obtained with car::Anova. The nine rows are Location, Factor A, Factor B, Replication within Location (L×Block), A×B, L×A, L×B, L×A×B and the Pooled Error (residual).
L <-factor(data_t$Location)A <-factor(data_t$FactorA)B <-factor(data_t$FactorB)Block <-factor(data_t$Block)Y <- data_t[[trait]]fit <-lm(Y ~ L + L:Block + A + B + A:B + L:A + L:B + L:A:B)atab <- car::Anova(fit, type ="II") # rows 1..8 = sources, row 9 = Residuals# mean squares = SS / df, in the module's row orderMS <- atab[, 1] / atab[, 2]names(MS) <-c("L", "A", "B", "LxBlock", "AxB", "LxA", "LxB", "LxAxB", "Error")MSABL <- MS["LxAxB"] # three-way interaction mean squareMSP <- MS["Error"] # pooled error mean square
5.4 Model-Dependent F-Tests of the Main Effects
The interactions and the pooled error are always tested against the residual. The error term used for Location, Factor A and Factor B depends on the pooling model (Model 4, both factors and location fixed, is the default).
dfABL <- atab[8, 2] # df of L x A x BdfP <- atab[9, 2] # df of Pooled Errormodel <-"model_4"# "model_1", "model_2", "model_3", "model_4" (default)# choose the denominator MS and df for L, A and B under each pooling modeldenom <-switch(model,# A, B, Location all random: test all three against L x A x Bmodel_1 =list(L =c(MSABL, dfABL), A =c(MSABL, dfABL), B =c(MSABL, dfABL)),# factors fixed, location random: L vs Error; A, B vs L x A x Bmodel_2 =list(L =c(MSP, dfP), A =c(MSABL, dfABL), B =c(MSABL, dfABL)),# location fixed, factors random: L vs L x A x B; A, B vs Errormodel_3 =list(L =c(MSABL, dfABL), A =c(MSP, dfP), B =c(MSP, dfP)),# all fixed (default): everything vs Pooled Errormodel_4 =list(L =c(MSP, dfP), A =c(MSP, dfP), B =c(MSP, dfP)))F_and_p <-function(ms, df_num, ms_err, df_err) { Fv <- ms / ms_errc(F = Fv, p =pf(Fv, df_num, df_err, lower.tail =FALSE))}resL <-F_and_p(MS["L"], atab[1, 2], denom$L[1], denom$L[2])resA <-F_and_p(MS["A"], atab[2, 2], denom$A[1], denom$A[2])resB <-F_and_p(MS["B"], atab[3, 2], denom$B[1], denom$B[2])# interactions are always tested against the Pooled Error (car::Anova default F, p)# star codes: ** p <= 0.01, * 0.01 < p <= 0.05, NS otherwisestar <-function(p) ifelse(p <=0.01, "**", ifelse(p <=0.05, "*", "NS"))
5.5 Mean Comparison, CV, SEm, SEd and CD
Each source is compared with the model-matched error term. LSD.test is shown; HSD.test (TUKEY) and duncan.test (DMRT) take the same DFerror / MSerror arguments. SEm and SEd are formed from the replication count returned in the means table.
alpha <-0.05padj <-"none"# "none" (default), "bonferroni", "holm" or "BH"; LSD only# error term for a main effect follows the pooling model chosen above;# interaction sources use the Pooled Error (MSP, dfP)outA <- agricolae::LSD.test(Y, A, DFerror = denom$A[2], MSerror = denom$A[1],alpha = alpha, p.adj = padj)statA <- outA$statistics # includes CV and the CD (LSD) columnrA <- outA$means[1, 3] # replications behind each Factor A meanCV_A <- statA[1, 4] # coefficient of variation (%)CD_A <- statA[1, 6] # critical difference at alpha (p.adj = "none")SEm_A <-sqrt(statA[1, 1] / rA) # standard error of a meanSEd_A <-sqrt(2* statA[1, 1] / rA) # standard error of a difference# compact-letter grouping (ordered naturally); shown only when significantgroupsA <- outA$groups[gtools::mixedsort(rownames(outA$groups)), ]# --- interaction example: A x B against the Pooled Error ---AB <-factor(data_t$AxB)outAB <- agricolae::LSD.test(Y, AB, DFerror = dfP, MSerror = MSP,alpha = alpha, p.adj = padj)
Explore the entire Pooled Two-Factor RBD module in preview mode using our demo datasets (dataset1.csv, dataset2.csv, dataset3.csv). To submit suggestions or report a workflow issue, please use the discussion section below, or visit the official RAISINS website.
6 RAISINS Native Statistical Framework
RAISINS uses R for all its statistical computations. Every package used to generate major results is listed and demonstrated with examples, so results can be reproduced independently. These results are then organized and formatted on the RAISINS website along with visualisation to make them easier to use and interpret. RAISINS also has its own custom-built statistical tools for managing workflows, validating results, and generating reports. Details of these are not fully covered here, they’re shared with outside researchers only on request, and are subject to licensing terms.
7 Package References
R Core Team. (2025). R: A language and environment for statistical computing. R Foundation for Statistical Computing, Vienna, Austria. https://www.R-project.org/
de Mendiburu, F. (2023). agricolae: Statistical Procedures for Agricultural Research (R package version 1.3-7). https://doi.org/10.32614/CRAN.package.agricolae
Fox, J., & Weisberg, S. (2019). An R Companion to Applied Regression (3rd ed.). Sage, Thousand Oaks, CA. https://doi.org/10.32614/CRAN.package.car
Warnes, G. R., Bolker, B., & Lumley, T. (2023). gtools: Various R Programming Tools (R package version 3.9.5). https://doi.org/10.32614/CRAN.package.gtools
Aitken, A. C. (1935). On least squares and linear combinations of observations. Proceedings of the Royal Society of Edinburgh, 55, 42–48.
Gomez, K. A., & Gomez, A. A. (1984). Statistical Procedures for Agricultural Research (2nd ed.). John Wiley & Sons, New York.
Allaire, J. J., Xie, Y., Dervieux, C., McPherson, J., Luraschi, J., Ushey, K., Atkins, A., Wickham, H., Cheng, J., Chang, W., & Iannone, R. (2025). rmarkdown: Dynamic Documents for R (R package version 2.31). https://github.com/rstudio/rmarkdown