R: unexpected results from p.adjust (FDR)
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
BH correction procedure giving monotonous/repeatitive adjusted p-values
This is not a "problem" per se. Please have a look at these two posts for details on BH correction at
CrossValidated and
StackOverflow.
The data you have (assuming that it is properly preprocessed / normalized) suggests that there is no significant difference based on sex. There might be other confounding effects that you need to take into account though (batch, age, disease status, etc...).
How Does R Calculate the False Discovery Rate
The reason is that the FDR calculation ensures that FDR never increases as the p-value decreases. That's because you can always choose to set a higher threshold for your rejection rule if that higher threshold will get you a lower FDR.
In your case, your second hypothesis had a p-value of 0.0006
and an FDR of 0.010971585
, but the third hypothesis had a larger p-value and a smaller FDR. If you can achieve an FDR of 0.009120228
by setting your p-value threshold to 0.0019
, there is never a reason to set a lower threshold just to get a higher FDR.
You can see this in the code by typing p.adjust
:
...
}, BH = {
i <- lp:1L
o <- order(p, decreasing = TRUE)
ro <- order(o)
pmin(1, cummin(n/i * p[o]))[ro]
The cummin
function takes the cumulative minimum of the vector, going backwards in the order of p
.
You can see this in the Benjamini-Hochberg paper you link to, including in the definition of the procedure on page 293, which states (emphasis mine):
let k be the largest i for which P(i) <= i / m q*;
then reject all H_(i) i = 1, 2, ..., k
How to find orphan plugins in eclipse RCPs?
Here's a starting point (this applies for Eclipse 3.4 and later, when the P2 repository was introduced, earlier versions store their configuration differently. IIRC you could see all the plugins and features in platform.xml).
Create a new plugin project (New->Other->Plug-in Development->Plug-in Project) with the "Hello World" template then drop this code into the run method of the SampleAction.
Run the plugin as a test Eclipse Application and select Sample Menu->Sample Action, the plugins that don't belong to a feature will be output to the parent workspace's console. When I ran this there were quite a few more than I expected, I've had a few looks through and can't spot the logic error.
Edit, found logic error, was using the wrong array index used in innermost loop. Still not quite right though.
Edit 2. (Facepalm moment) Found the problem. Be sure to run the target workspace with all workspace and enabled target plugins enabled, or it will skew your results, obviously. If you install the plugin and dress it up a little bit you won't have this problem.
//get all the plugins that belong to features
IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
Map<Long, IBundleGroup> bundlesMap = new HashMap<Long, IBundleGroup>();
if (providers != null) {
for (int i = 0; i < providers.length; i++) {
IBundleGroup[] bundleGroups = providers[i].getBundleGroups();
System.out.println("Bundle groups:");
for (int j = 0; j < bundleGroups.length; j++) {
Bundle[] bundles = bundleGroups[j] == null ? new Bundle[0] : bundleGroups[j]
.getBundles();
System.out.println(bundleGroups[j].getIdentifier());
for (int k = 0; k < bundles.length; k++) {
bundlesMap.put(bundles[k].getBundleId(), bundleGroups[j]);
}
}
}
}
BundleContext bundleContext = Activator.getDefault().getBundle().getBundleContext();
if(bundleContext instanceof BundleContextImpl) {
Bundle[] bundles = ((BundleContextImpl)bundleContext).getBundles();
System.out.println("Orphan Bundles:");
for (int i = 0; i < bundles.length; i++) {
if(!bundlesMap.containsKey(bundles[i].getBundleId())) {
System.out.println(bundles[i].getSymbolicName());
}
}
}
Related Topics
Move a Column to First Position in a Data Frame
Define All Functions in One .R File, Call Them from Another .R File. How, If Possible
What Best Practices Do You Use for Programming in R
What Is the Knitr Equivalent of 'R Cmd Sweave Myfile.Rnw'
How to Change the Default Font Size in Ggplot2
Change the Index Number of a Dataframe
How to Convert Ensembl Id to Gene Symbol in R
How Does the Removesparseterms in R Work
Hiding Personal Functions in R
Circular Heatmap That Looks Like a Donut
Jupyter-Client Has to Be Installed But "Jupyter Kernelspec --Version" Exited with Code 127
Reordering Columns in a Large Dataframe
To Find Whether a Column Exists in Data Frame or Not
How to Apply Function Over Each Matrix Element's Indices
Ggplot2 Legend to Bottom and Horizontal
Displaying Data in the Chart Based on Plotly_Click in R Shiny