=== SPSS script to Perform the Benjamini and Hochberg FDR procedure === This procedure may also be computed using the [[FAQ/pvs|spreadsheet here]]. Keselman HJ, Cribbie R and Holland B (1999) compared several pairwise comparison tests and found the FDR approach to be the most powerful when more than 6 pairwise tests were performed e.g. when comparing all possible pairs of means for five groups. Benjamini and Hochberg (1995) also show FDR has higher power compared to other procedures including a p-value adjustment procedure due to Hochberg (1988) which, in turn, is shown as having higher power than both Bonferroni and Holm methods for multiple testing in repeated measures by Lix and Sajobi (2010). The FDR (Benjamini and Hochberg, 1995) is a stepdown procedure using a prescribed alpha usually 0.05 for testing '''in advance of the p-value testing''' (see Ernst Wit's discussion in Benjamini (2010)) and so the above spreadsheet should be used for hypothesis testing of multiple p-values. See [[FAQ/SpssBonferroni| here]] for a warning about using ''exact'' p-values instead of statements of form ''p0)*CMAX(((CMAX(ccomp) &* (diff LE 0)) EQ ccomp) &* pvals) . SAVE {rnk, pvals, alpha, ccmpmx} / OUTFILE = * / VARIABLES = index,pvals,alpha,fdrsig . END MATRIX . SORT CASES BY index (A) . EXPORT OUTFILE = out . IMPORT FILE = out / KEEP = pvals alpha fdrsig . FORMAT pvals (F5.3) . FORMAT alpha (F5.3) . FORMAT fdrsig (F1.0) . VALUE LABELS fdrsig 1 'Sig' 0 'Nonsig' . SET RESULTS = LISTING . DO IF $CASENUM EQ 1 . PRINT EJECT /'P Value' 1 'FDR Criterion' 9 'FDR Significance' 24 . END IF . PRINT / pvals (T3 F5.3) alpha (T17, F5.3) fdrsig (T39, F1.0) . EXECUTE . }}} This produces the following output: {{{ P Value FDR Criterion FDR Significance .001 .050 1 .005 .050 1 .017 .050 1 .021 .050 1 .023 .050 1 .036 .050 0 .041 .050 0 .042 .050 0 .070 .050 0 .100 .050 0 }}} === R Code to Perform the Benjamini and Hochberg FDR procedure === {{{ [Insert P values in any order] pvalue <- c(0.021,0.001,0.017,0.041,0.005,0.036,0.042,0.023,0.07,0.1) sorted.pvalue<-sort(pvalue) sorted.pvalue j.alpha <- (1:10)*(.05/10) diff <- sorted.pvalue-j.alpha neg.diff <- diff[diff<0] pos.diff <- neg.diff[length(neg.diff)] index <- diff==pos.diff p.cutoff <-sorted.pvalue[index] p.cutoff p.sig <- pvalue[pvalue <= p.cutoff] p.sig }}} === R Output === {{{ > pvalue<-c(0.021,0.001,0.017,0.041,0.005,0.036,0.042,0.023,0.07,0.1) > sorted.pvalue <- sort(pvalue) > sorted.pvalue [sorted P values in ascending order] [1] 0.001 0.005 0.017 0.021 0.023 0.036 0.041 0.042 0.070 0.100 > j.alpha <- (1:10) * (0.05/10) > diff <- sorted.pvalue - j.alpha > neg.diff <- diff[diff < 0] > pos.diff <- neg.diff[length(neg.diff)] > index <- diff == pos.diff > p.cutoff <- sorted.pvalue[index] > p.cutoff [1] 0.023 > p.sig <- pvalue[pvalue <= p.cutoff] > p.sig [significant p values by B-H method]: [1] 0.021 0.001 0.017 0.005 0.023 }}} A more elegant version of the above R code (by Adam Wagner) is given below which returns the maximum p-value which is below the threshold based on FDR. {{{ # FDR implementation, adapted from Peter Watson's Stats wiki entry by Adam Wagner # http://imaging.mrc-cbu.cam.ac.uk/statswiki/FAQ/FDR # fdrPValue # Inputs # pValues.....the P-values that we wish to apply the FDR correction # multiple correction to; can be a vector or matrix # alpha.....the size of alpha we wish to use; default=0.05 # Outputs.....the largest P-value that is still significant with FDR applied -or- # halts execution if no P-values are significant fdrPValue <- function(pValues, alpha=0.05){ sortedPValues <- sort(pValues) # Error catching - stop if there are no p-values smaller than alpha if (sum(sortedPValues