rexperimental-design

With agricolae, how to add spatial constraints in experimental designs to prevent adjacent treatments?


I’m currently using the agricolae package in R to generate randomized complete block designs (RCBD) with six treatments and four replicates. While the randomization works as expected, I’ve noticed that sometimes the same treatment appears adjacent to itself across blocks (e.g., the same treatment in neighboring plots). In our field trials, the company prefers to avoid such situations due to potential neighborhood effects (e.g., drift, root interference).

My questions are: Is it possible to prevent this adjacency directly within agricolae, by imposing spatial constraints in the design?

If not, would the best approach be to loop over randomizations until a spatially acceptable layout is found?

Are there any other packages or strategies you would recommend that allow more control over treatment layout, while still being compatible with agricolae?

Below is a minimal working example showing how I generate the design and plot it. Any suggestions on how to add spatial constraints would be greatly appreciated!

# Install agricolae and agricolaeplotr if needed
install.packages("agricolae")
install.packages("agricolaeplotr")

library(tidyverse)
library(agricolae)
library(agricolaeplotr) # for plot_rcbd()

# Define treatment names
fertilizers <- c("Growth2000",
                "Starter50",
                "WellGrown",
                "MaxDev",
                "SuperBoost",
                "NatFertilizer")

# Generate a randomized complete block design (RCBD)
RCBD <- design.rcbd(trt = treatments,
                    r = 4,
                    seed = 2025)

# Plot the field layout
plot_rcbd(design = RCBD,
          factor_name = "fertilizers",      # Column containing the treatment levels
          treatment_label = "fertilizers",  # Display treatment names in the plot
          width = 2,   # Width of each plot (in meters)
          height = 1)  # Height of each block (in meters)

This plot shows an example of what I’d like to avoid: the Growth2000 treatment appears in adjacent plots in blocks 3 and 4, first column.

exp design with neighboring effect

Thank you in advance for your feedback and any ideas you might have to control for treatment adjacency in the field layout.

Best regards.


Solution

  • I had a quick look at the agricolae package but didn't see any design that did what you wanted, so I modified the design.rcbd function so that it checks for the previous assignment and resamples until the plots are all different. I made only six modifications (shown by lines with #).

    design.rcbd2 <- function(trt, r, serie = 2, seed = 0, kinds = "Super-Duper", 
                             first = TRUE, continue = FALSE, randomization = TRUE) {
      number <- 10
      if (serie > 0) 
        number <- 10^serie
      ntr <- length(trt)
      if (seed == 0) {
        genera <- runif(1)
        seed <- .Random.seed[3]
      }
      set.seed(seed, kinds)
      parameters <- list(design = "rcbd", trt = trt, r = r, serie = serie, 
                         seed = seed, kinds = kinds, randomization)
      # mtr <- trt
      mtr <- vector(mode="list", length=r)  ### Modify above line
      if (randomization) 
        # mtr <- sample(trt, ntr, replace = FALSE)
        mtr[[1]] <- sample(trt, ntr, replace = FALSE)  ### Modify
      block <- c(rep(1, ntr))
      for (y in 2:r) {
        block <- c(block, rep(y, ntr))
        mtr[[y]] <- sample(trt, ntr, replace = FALSE)  ### Insert
        while(any(mtr[[y]]==mtr[[y-1]])) {   # Insert
          if (randomization) 
            # mtr <- c(mtr, sample(trt, ntr, replace = FALSE))
            mtr[[y]] <- sample(trt, ntr, replace = FALSE)  ### Modify above line
        }
      }
      mtr <- unlist(mtr)   # Insert
      plots <- block * number + (1:ntr)
      book <- data.frame(plots, block = as.factor(block), trt = as.factor(mtr))
      names(book)[3] <- c(paste(deparse(substitute(trt))))
      names(book)[3] <- c(paste(deparse(substitute(trt))))
      if (continue) {
        start0 <- 10^serie
        if (serie == 0) 
          start0 <- 0
        book$plots <- start0 + 1:nrow(book)
      }
      outdesign <- list(parameters = parameters, sketch = matrix(book[, 3], byrow = TRUE, ncol = ntr), book = book)
      return(outdesign)
    }
    

    Test it:

    RCBD2 <- design.rcbd2(trt = fertilizers,
                 r = 4,
                 randomization=TRUE,
                 seed = 2025)
    
    plot_rcbd(design = RCBD2,
              factor_name = "fertilizers",      # Column containing the treatment levels
              treatment_label = "fertilizers",  # Display treatment names in the plot
              width = 2,   # Width of each plot (in meters)
              height = 1)  # Height of each block (in meters)
    

    enter image description here