One-way hypothesis test in limma
2
0
Entering edit mode
s1437643 ▴ 20
@s1437643-9524
Last seen 4.6 years ago

Is it possible to test for fold-change in only one direction (LFC > 0) using the treat function from limma? Similar to using the altHypothesis argument in the results function from DESeq2?

I tried myself to introduce some changes to the code in treat to perform this:

lfc <- 0
se <- stdev.unscaled*sqrt(fit$s2.post)
tstat <- (coefficients-lfc)/se
fit$t <- array(0,dim(coefficients),dimnames=dimnames(coefficients))
fit$p.value <- pt(tstat, df=df.total, lower.tail=FALSE)
tstat <- pmax(tstat,0)
fit$t <- tstat
fit$treat.lfc <- lfc

This seems correct, but wanted to double-check incase a method was already implemented.

limma • 1.7k views
ADD COMMENT
2
Entering edit mode
Aaron Lun ★ 28k
@alun
Last seen 3 hours ago
The city by the bay

That seems fine to me.

<del>Keep in mind that the usual two-sided test in treat() considers the null hypothesis where the true log-fold changes are distributed at -lfc and lfc with 50% probability each.</del> Edit: not quite right, that assumption is not actually necessary. The null hypothesis is just that the log-fold change is somewhere inside [-lfc, lfc]. We test against both the boundaries to account for the fact that a true log-fold change of lfc can still generate observed log-fold changes that are less than -lfc, just by random sampling, and vice versa. The two-sided p-value is obtained by adding the two p-values from both boundaries. Your one-sided test considers a different null hypothesis where the true log-fold change is lfc alone. This is probably the sensible thing to do, but it means that the nulls are not exactly comparable, which is something to be aware of.

Also, I would avoid hacking into treat() like you've done here. If you know enough to compute your own test statistics, then you know enough to form your own output data.frame from fit. Perhaps there is an argument for adding a one-sided test option to limma functions, but this tends to be a very bespoke setting - I have only ever done this on occasion for ChIP-seq analysis, and never for RNA-seq.

ADD COMMENT
0
Entering edit mode

Many thanks, Aaron.

ADD REPLY
0
Entering edit mode
@gordon-smyth
Last seen 16 minutes ago
WEHI, Melbourne, Australia

It would be easy to implement a one-sided test in treat(), pretty much as you've done. The two-sided test was much more difficult to derive! When the threshold lfc > 0, the two-sided p-value can't be derived from the one-sided p-values or vice-versa.

I haven't implemented one-sided tests in treat() because I have yet to see a real experiment for which that would be scientifically the right thing to do. I don't want to give users rope to hang themselves with.

ADD COMMENT
0
Entering edit mode

So if one wanted to implement one-sided tests (LFC > LT and LFC < -LT seperately), with an lfc threshold of LT, would the code look like this?

# testing LFC > 0 (condition1 > condition2 for the given contrast, same code as the original post)
lfc <- log2(2)#arbitrary lfc threshold
se <- stdev.unscaled*sqrt(fit$s2.post)
tstat <- (coefficients-lfc)/se          
fit$t <- array(0,dim(coefficients),dimnames=dimnames(coefficients))
fit$p.value <- pt(tstat, df=df.total, lower.tail=FALSE)
tstat <- pmax(tstat,0)
fit$t <- tstat
fit$treat.lfc <- lfc
# testing LFC < 0 (condition1 < condition2 for the given contrast)
lfc <- log2(2) #arbitrary lfc threshold
se <- stdev.unscaled*sqrt(fit$s2.post)
tstat <- ((-coefficients)-lfc)/se          
fit$t <- array(0,dim(coefficients),dimnames=dimnames(coefficients))
fit$p.value <- pt(tstat, df=df.total, lower.tail=FALSE)
tstat <- pmax(tstat,0)
fit$t <- tstat
fit$treat.lfc <- lfc

P.S. I am interested in the one-sided p-values because I will use them as input for GO enrichment, so I want to know when GO terms are up vs. down regulated for each comparison

ADD REPLY

Login before adding your answer.

Traffic: 780 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6