Project: s41467-024-50841-9 | Function: nullStoc (r)

system: You are an expert R programmer implementing algorithms from scientific papers.
Complete the masked function based on the algorithm description.
Follow R best practices and maintain consistent code style.
Return **only** the complete R function code.

user: Complete this R function:

**DESCRIPTION:** Performs stochasticity analysis using null models to quantify the relative importance of deterministic vs. stochastic processes in shaping community assembly patterns

**KEY TERMS:** {
  "nullStoc": "null model stochasticity analysis",
  "RC": "Raup-Crick metric",
  "SES": "standardized effect size"
}

**CONTEXT CODE:** 
summStoc <- function(ob_dis, per_dis_l, stats = c("RC", "SES", "ST", "MST", "NST")) {
  ob_sim <- 1 - ob_dis
  # per_ma_l <- lapply(1:length(per_madis), function(k) per_madis[[k]][[1]])
  # per_dis_l <- lapply(1:length(per_madis), function(k) per_madis[[k]][[2]])
  per_dis <- Reduce("+", per_dis_l) / length(per_dis_l)
  per_sim <- 1 - per_dis
  
  RC_Radio <- SES_Radio <- ST_Radio <- MST_Radio <- NST_Radio <- NA
  xx <- NULL
  
  if ("RC" %in% stats) {
    r1 <- sapply(1:length(per_dis_l), function(k) ifelse(ob_dis > per_dis_l[[k]], 1, 0)) %>% rowSums()
    r2 <- sapply(1:length(per_dis_l), function(k) ifelse(ob_dis == per_dis_l[[k]], 1, 0)) %>% rowSums()
    
    RC_Radio <- ((r1 + r2 * 0.5) / length(per_dis_l) - 0.5) * 2
  }
  
  if ("SES" %in% stats) {
    # bdisp_ob <- vegan::betadisper(ob_dis, group = rep(1, nrow(as.matrix(ob_sim))), type = "centroid")$distances
    # bdisp_per <- lapply(per_dis_l, vegan::betadisper, group = rep(1, times = nrow(as.matrix(ob_sim))), type = "centroid") %>% sapply("[[", "distances")
    SES_Radio <- (c(ob_dis) - rowMeans(sapply(per_dis_l, c))) / apply(sapply(per_dis_l, c), 1, stats::sd)
    # SES_Radio <- (bdisp_ob - rowMeans(bdisp_per)) / apply(bdisp_per, 1, stats::sd)
    # SES_Radio <- c(SES_Radio, rep(NA, length(ob_sim) - length(SES_Radio)))
    # SES_Radio <- as.vector((ob_dis - per_dis) / apply(Reduce("cbind", per_dis_l), 1, sd))
  }
  
  if ("ST" %in% stats) {
    ST_Radio1 <- as.vector(per_sim / ob_sim)
    ST_Radio <- ST_Radio1
    ST_Radio[which(ST_Radio1 > 1)] <- ((1 - per_sim) / (1 - ob_sim))[which(ST_Radio1 > 1)]
    ST_Radio[which(is.nan(ST_Radio1))] <- ((1 - per_sim) / (1 - ob_sim))[which(is.nan(ST_Radio1))]
  }
  
  if ("MST" %in% stats) {
    MST_Radio <- as.vector((per_sim / ob_sim) * ((1 - ob_sim) / (1 - per_sim)))
    MST_Radio[which(MST_Radio > 1)] <- ((ob_sim / per_sim) * ((1 - per_sim) / (1 - ob_sim)))[which(MST_Radio > 1)]
    MST_Radio[which(is.nan(MST_Radio))] <- 1
  }
  
  if ("NST" %in% stats) {
    group <- data.frame(rep(1, nrow(as.matrix(ob_sim)))); rownames(group) <- rownames(as.matrix(ob_sim))
    NST_Radio <- NST::cNST(ob_dis, per_dis_l, group = group)$index.pair.grp$NST.ij.dis
  }
  xx <- data.frame(RC_Radio, SES_Radio, ST_Radio, MST_Radio, NST_Radio)[, match(stats, c("RC", "SES", "ST", "MST", "NST")), drop = F]
  names(xx) <- stats
  as.data.frame(xx)
}


nullStoc <- function(comm, null_model, sp_freq = "fix", samp_rich = "fix", dist_method = "bray", reps = 1000, nworker = 10, stats = c("RC", "SES", "ST", "MST", "NST")) {
  stop("Function implementation has been masked")
}


Complete the function implementation replacing "stop("Not implemented")".