Statistical analysis decides which metabolites differ between conditions and whether a discriminant model is real. The two endemic failure modes it guards against are overfitting (in p >> n, supervised models separate pure noise -- a score plot proves nothing without permutation-validated Q2) and false-discovery inflation (thousands of correlated tests on small n yield long "significant" lists that do not replicate). It covers transformation/scaling as an explicit modeling choice, unsupervised structure (PCA/HCA for QC), validated PLS-DA/OPLS-DA, univariate testing with covariate adjustment, and dependence-aware multiple testing.
# Python
pip install scipy statsmodels numpy pandas matplotlib scikit-learn
# R
BiocManager::install("ropls")
install.packages(c("mixOmics", "lme4", "qvalue"))
Conceptual prerequisites: decide the scaling (Pareto vs unit-variance is a hypothesis, not a default), know whether the normalization imposed closure (total-area/PQN), distinguish technical from biological zeros, and identify the experimental unit (the subject, not the injection) before any group test.
Tell your AI agent what you want to do: - "Run PCA with Pareto scaling and check whether my pooled QC samples cluster tightly" - "Fit an OPLS-DA model and permutation-test it -- I only trust it if pQ2 is small" - "Run Welch t-tests between case and control with explicit BH FDR and fold changes" - "Fit a linear mixed model per metabolite for my longitudinal design" - "Show me whether my top hits survive switching from Pareto to unit-variance scaling"
"Transform and Pareto-scale my feature table, run PCA, and color the scores by batch and injection order to check for drift." "Re-run the PCA with unit-variance scaling and tell me whether the top loadings change."
"Build an OPLS-DA model between disease and control, run 1000 permutations, and report R2X, R2Y, Q2, and pQ2." "Put a PCA score plot next to my PLS-DA plot so I can see whether the separation is real or supervised-only." "Extract VIP scores but only after the model passes the permutation test, and cross-check them against my univariate hits."
"Run Welch t-tests in Python with Benjamini-Hochberg correction and report log2 fold changes." "Fit a per-metabolite linear model adjusting for age, sex, and BMI." "My features are heavily correlated -- use an effective-number-of-tests correction instead of Bonferroni."
"Check whether my discriminant result survives changing the scaling and the imputation method." "I have a validation cohort -- estimate external performance, not just cross-validated discovery performance."
ropls::opls() defaults scaleC = "standard" (unit-variance), not Pareto -- set it explicitly.permI well above the ropls default of 20 (>= 1000) or the permutation p-value just reports the grid granularity.p.adjust defaults to Holm (FWER) and statsmodels multipletests to Holm-Sidak -- always pass BH explicitly.equal_var=False in scipy.stats.ttest_ind() for Welch; group variances differ, especially near the LOD.log2(mean_ratio).