This issue arose when I was trying to use p.adjust
to run FDR adjustment on a vector of p-values. The problem was that many of the resultant p-values were ident
The method is working fine. You just don't understand what the algorithm is doing fully apparently. I would suggest reading up a little bit about the procedure (Wikipedia Link).
n <- 40
p <- runif(n, 0, 1)
adjusted.p <- p.adjust(p, "fdr") #same as p.adjust(p, "BH")
## Let's recreate. Going back to the paper we
## can construct a q-value by sorting the p-values
## and then applying the transformation:
## q_i = p_i*n/i
## Where p_i is the ith smallest p-value
## Sort the p-values and keep track of the order
id <- order(p)
tmp <- p[id]
(q <- tmp*n/(1:n))
# [1] 2.0322183 1.0993436 1.2357457 1.1113084 0.9282536 0.7877181 0.7348436
# [8] 0.7204077 0.6587102 0.6289974 0.9205222 0.8827835 0.8600234 0.8680704
#[15] 1.1532693 1.1055951 1.0451330 1.1314681 1.1167659 1.1453142 1.1012847
#[22] 1.0783747 1.0672471 1.0500311 1.0389407 1.0089661 1.0117881 0.9917817
#[29] 0.9892826 0.9668636 0.9844052 0.9792733 1.0000320 0.9967073 0.9707149
#[36] 0.9747723 0.9968153 0.9813367 1.0058445 0.9942353
## However there is one more portion to the adjustment
## We don't want a p-value of .02 getting
## a larger q-value than a p-value of .05
## so we make sure that if a smaller q-value
## shows up in the list we set all of
## the q-values corresponding to smaller p-values
## to that corresponding q-value.
## We can do this by reversing the list
## Keeping a running tally of the minimum value
## and then re-reversing
new.q <- rev(cummin(rev(q)))
## Put it back in the original order
new.q[order(id)]
# [1] 0.6289974 0.9668636 0.6289974 0.6289974 0.6289974 0.9707149 0.9707149
# [8] 0.8600234 0.9668636 0.6289974 0.9707149 0.9668636 0.9668636 0.9813367
#[15] 0.9668636 0.9668636 0.9668636 0.9707149 0.9668636 0.9668636 0.6289974
#[22] 0.9942353 0.8600234 0.6289974 0.9668636 0.6289974 0.6289974 0.8680704
#[29] 0.9668636 0.9668636 0.9668636 0.9942353 0.9707149 0.9813367 0.9668636
#[36] 0.8600234 0.6289974 0.9668636 0.9668636 0.9747723
## This should match the adjustment
adjusted.p
# [1] 0.6289974 0.9668636 0.6289974 0.6289974 0.6289974 0.9707149 0.9707149
# [8] 0.8600234 0.9668636 0.6289974 0.9707149 0.9668636 0.9668636 0.9813367
#[15] 0.9668636 0.9668636 0.9668636 0.9707149 0.9668636 0.9668636 0.6289974
#[22] 0.9942353 0.8600234 0.6289974 0.9668636 0.6289974 0.6289974 0.8680704
#[29] 0.9668636 0.9668636 0.9668636 0.9942353 0.9707149 0.9813367 0.9668636
#[36] 0.8600234 0.6289974 0.9668636 0.9668636 0.9747723