# How can I convert a q-value distribution to a p-value distribution?

Let's say I have a vector of q-values, which allow for handling multiple hypothesis testing by controlling the false discovery rate. Usually, these q-values will be generated from a distribution of p-values.

However, what if I don't have the original p-value distribution, only the vector of q-values? Is there a way to convert from the q-values to the p-values?

• By q-values are you referring to Benjamini-Hochberg adjusted p-value or to local fdr? Mar 4, 2013 at 19:48
• @JohnRos: local FDR, such as that in Storey 2003. Mar 4, 2013 at 19:59
• @JohnRos: Is local FDR differently defined from FDR and pFDR?
– Tim
Jul 14, 2013 at 15:44
• @Tim: Local FDR is the false discovery rate for a single p-value. But in any case I shouldn't really have said local FDR- the q-value is the pFDR analogue of the p-value: see here. The idea is that if one rejects the null for all q-values less than q, the expected FDR will be q. Jul 14, 2013 at 16:37

You can convert from a q-value distribution to a p-value distribution rather simply (indeed, it's easier than the other way around!).

The way to do this in R is (explanation is in the comments):

convert.qval.pval = function(qvalues) {
# you need to know the estimate of pi0 used to create the q-value
# that's the maximum q-value (or very, very close to it)
pi0 = max(qvalues)
# compute m0, the estimated number of true nulls
m0 = length(qvalues) * pi0
# then you multiply each q-value by the proportion of true nulls
# expected to be under it (the inverse of how you get there from
# the p-value):
return(qvalues * rank(qvalues) / m0)
}


It can be done in one line as

qvalues * rank(qvalues) / (max(qvalues) * length(qvalues))


As a demonstration, using the package qvalue:

library(qvalue)
pvals = replicate(1000, t.test(rnorm(100, .1))$p.value) qvals = qvalue(pvals)$qvalue
plot(pvals, convert.qval.pval(qvals))