Standardise trait columns: z-score ('zscore'), 0-1 range ('minmax'), or unit-variance without centering ('unit'). Returns data frame with scaled values.
scale_traits <- function(df, method = "zscore", cols = NULL) {
if (is.null(cols)) cols <- names(df)[sapply(df, is.numeric)]
scale_fn <- switch(method,
zscore = function(x) (x - mean(x, na.rm=TRUE)) / sd(x, na.rm=TRUE),
minmax = function(x) {
r <- range(x, na.rm = TRUE)
(x - r[1]) / (r[2] - r[1])
},
unit = function(x) x / sd(x, na.rm = TRUE),
stop("method must be 'zscore', 'minmax', or 'unit'")
)
df[, cols] <- lapply(df[, cols, drop = FALSE], scale_fn)
df
}
# Example
scaled <- scale_traits(iris, method = "zscore")
apply(scaled[, 1:4], 2, mean) # should be ~0