Learn / Inside the pipeline / 04 · prepare

Many tests, one year: max or pool

An accession often gets tested more than once in the same year — different substrates, different dormancy treatments, a repeated assay. Before any interval or curve math, each accession needs one value per year. Two defensible strategies:

MAX keeps the single replicate with the highest germination that year (ties broken by larger sample). The logic: treatments differ in how well they break dormancy, and the best treatment is the closest measure of how many seeds are actually still alive. This is the pipeline's default.

POOLED sums counts across replicates — conservative, and statistically cleaner if the replicates really are exchangeable draws from the same lot. It punishes the accession when one treatment underperforms, which is exactly wrong if that treatment simply failed to break dormancy.

Whichever you choose, choose it once, name it in your methods, and apply it before both the interval logic and the curve fits — a pipeline that collapses differently in different places will contradict itself.

Build it yourself
library(dplyr)

collapse_by_year <- function(df, strategy = c("max", "pooled")) {
  strategy <- match.arg(strategy)
  grouped <- df %>%
    filter(!is.na(YearsDifference), NumberSown > 0, NumberGermin >= 0) %>%
    group_by(Family, TaxonName, AcquisitionNum, StoreDryCode, YearsDifference)
  if (strategy == "pooled") {
    grouped %>%
      summarise(NumberSown   = sum(NumberSown),
                NumberGermin = sum(NumberGermin), .groups = "drop")
  } else {  # max: best replicate, tie -> larger sample
    grouped %>%
      mutate(p = NumberGermin / NumberSown) %>%
      arrange(desc(p), desc(NumberSown), .by_group = TRUE) %>%
      slice(1) %>% ungroup() %>% select(-p)
  } %>%
    mutate(PctGermin = 100 * NumberGermin / NumberSown)
}
The math behind this step: Replicates: same seeds, same year, different answers
Counts are the truth; percentages are a courtesyThe early-window baseline: what 70% is 70% of