多重假设检验与Bonferroni校正、FDR校正

本文介绍了在生物信息学研究中如何进行多重假设检验校正,包括Bonferroni校正和False Discovery Rate(FDR)校正两种方法。通过具体实例说明了如何应用这两种校正方法来减少假阳性结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

总结起来就三句话:
(1)当同一个数据集有n次(n>=2)假设检验时,要做多重假设检验校正
(2)对于Bonferroni校正,是将p-value的cutoff除以n做校正,这样差异基因筛选的p-value cutoff就更小了,从而使得结果更加严谨
(3)FDR校正是对每个p-value做校正,转换为q-value。q=p*n/rank,其中rank是指p-value从小到大排序后的次序。
举一个具体的实例:
我们测量了M个基因在A,B,C,D,E一共5个时间点的表达量,求其中的差异基因,具体做法:
(1)首先做ANOVA,确定这M个基因中有哪些基因至少出现过差异
(2)5个时间点之间两两比较,一共比较5*4/2=10次,则多重假设检验的n=10
(3)每个基因做完10次假设检验后都有10个p-value,做多重假设检验校正(n=10),得到q-value

(4)根据q-value判断在哪两组之间存在差异


通过T检验等统计学方法对每个蛋白进行P值的计算。T检验是差异蛋白表达检测中常用的统计学方法,通过合并样本间可变的数据,来评价某一个蛋白在两个样本中是否有差异表达。
但是由于通常样本量较少,从而对总体方差的估计不很准确,所以T检验的检验效能会降低,并且如果多次使用T检验会显著增加假阳性的次数。
例如,当某个蛋白的p值小于0.05(5%)时,我们通常认为这个蛋白在两个样本中的表达是有差异的。但是仍旧有5%的概率,这个蛋白并不是差异蛋白。那么我们就错误地否认了原假设(在两个样本中没有差异表达),导致了假阳性的产生(犯错的概率为5%)。
如果检验一次,犯错的概率是5%;检测10000次,犯错的次数就是500次,即额外多出了500次差异的结论(即使实际没有差异)。为了控制假阳性的次数,于是我们需要对p值进行多重检验校正,提高阈值。

方法一.Bonferroni
“最简单严厉的方法”
例如,如果检验1000次,我们就将阈值设定为5%/ 1000 = 0.00005;即使检验1000次,犯错误的概率还是保持在N×1000 = 5%。最终使得预期犯错误的次数不到1次,抹杀了一切假阳性的概率。
该方法虽然简单,但是检验过于严格,导致最后找不到显著表达的蛋白(假阴性)。
方法二.FalseDiscovery Rate
“比较温和的方法校正P值”
FDR(假阳性率)错误控制法是Benjamini于1995年提出的一种方法,基本原理是通过控制FDR值来决定P值的值域。相对Bonferroni来说,FDR用比较温和的方法对p值进行了校正。其试图在假阳性和假阴性间达到平衡,将假/真阳性比例控制到一定范围之内。例如,如果检验1000次,我们设定的阈值为0.05(5%),那么无论我们得到多少个差异蛋白,这些差异蛋白出现假阳性的概率保持在5%之内,这就叫FDR<5%。
那么我们怎么从p value 来估算FDR呢,人们设计了几种不同的估算模型。其中使用最多的是Benjamini and Hochberg方法,简称BH法。虽然这个估算公式并不够完美,但是也能解决大部分的问题,主要还是简单好用!
FDR的计算方法
除了可以使用excel的BH计算方法外,对于较大的数据,我们推荐使用R命令p.adjust。


1.我们将一系列p值、校正方法(BH)以及所有p值的个数(length(p))输入到p.adjust函数中。
2.将一系列的p值按照从大到小排序,然后利用下述公式计算每个p值所对应的FDR值。
公式:p * (n/i), p是这一次检验的pvalue,n是检验的次数,i是排序后的位置ID(如最大的P值的i值肯定为n,第二大则是n-1,依次至最小为1)。
3.将计算出来的FDR值赋予给排序后的p值,如果某一个p值所对应的FDR值大于前一位p值(排序的前一位)所对应的FDR值,则放弃公式计算出来的FDR值,选用与它前一位相同的值。因此会产生连续相同FDR值的现象;反之则保留计算的FDR值。
4. 将FDR值按照最初始的p值的顺序进行重新排序,返回结果。
最后我们就可以使用校正后的P值进行后续的分析了。

要监听微信消息,您需要使用微信开放平台提供的API接口。首先,您需要在微信开放平台注册并创建应用程序。然后,您可以使用Java编写代码来访问API接口,以便获取和处理微信消息。 以下是一个简单的示例,用于从微信服务器接收消息并处理它们: 1. 创建一个Servlet来处理微信服务器的请求: ```java @WebServlet("/wechat") public class WechatServlet extends HttpServlet { private static final long serialVersionUID = 1L; private static final String TOKEN = "your_token"; protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String signature = request.getParameter("signature"); String timestamp = request.getParameter("timestamp"); String nonce = request.getParameter("nonce"); String echostr = request.getParameter("echostr"); if (checkSignature(signature, timestamp, nonce)) { response.getWriter().print(echostr); } else { response.getWriter().print("invalid signature"); } } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { ServletInputStream inputStream = request.getInputStream(); String xml = IOUtils.toString(inputStream); // Parse the received XML message Map<String, String> message = MessageUtil.parseXml(xml); // Process the received message String responseXml = MessageUtil.processMessage(message); response.setCharacterEncoding("UTF-8"); response.setContentType("text/xml"); response.getWriter().print(responseXml); } private boolean checkSignature(String signature, String timestamp, String nonce) { List<String> params = new ArrayList<String>(); params.add(TOKEN); params.add(timestamp); params.add(nonce); Collections.sort(params); String str = ""; for (String param : params) { str += param; } String encrypted = DigestUtils.sha1Hex(str); return encrypted.equals(signature); } } ``` 2. 创建一个工具类来帮助解析和处理接收到的消息: ```java public class MessageUtil { public static Map<String, String> parseXml(String xml) throws Exception { Map<String, String> map = new HashMap<String, String>(); Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xml))); Element root = document.getDocumentElement(); NodeList nodeList = root.getChildNodes(); for (int i = 0; i < nodeList.getLength(); i++) { Node node = nodeList.item(i); if (node instanceof Element) { Element element = (Element) node; map.put(element.getNodeName(), element.getTextContent()); } } return map; } public static String processMessage(Map<String, String> message) { String fromUserName = message.get("FromUserName"); String toUserName = message.get("ToUserName"); String msgType = message.get("MsgType"); String content = message.get("Content"); String responseXml = ""; if (msgType.equals("text")) { // Process text messages String responseContent = "您发送的是文本消息:" + content; responseXml = buildTextMessage(fromUserName, toUserName, responseContent); } else if (msgType.equals("image")) { // Process image messages } else if (msgType.equals("voice")) { // Process voice messages } else if (msgType.equals("video")) { // Process video messages } else if (msgType.equals("location")) { // Process location messages } else if (msgType.equals("link")) { // Process link messages } else if (msgType.equals("event")) { // Process event messages } return responseXml; } private static String buildTextMessage(String fromUserName, String toUserName, String content) { String responseXml = "<xml>"; responseXml += "<ToUserName><![CDATA[" + fromUserName + "]]></ToUserName>"; responseXml += "<FromUserName><![CDATA[" + toUserName + "]]></FromUserName>"; responseXml += "<CreateTime>" + System.currentTimeMillis() / 1000 + "</CreateTime>"; responseXml += "<MsgType><![CDATA[text]]></MsgType>"; responseXml += "<Content><![CDATA[" + content + "]]></Content>"; responseXml += "</xml>"; return responseXml; } } ``` 3. 在您的应用程序中,您需要使用Java HTTP客户端来向微信服务器发送请求并接收响应。例如,您可以使用Apache HttpClient,如下所示: ```java HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token=ACCESS_TOKEN"); StringEntity entity = new StringEntity("your_message", "UTF-8"); post.setEntity(entity); HttpResponse response = client.execute(post); String responseJson = EntityUtils.toString(response.getEntity(), "UTF-8"); ``` 4. 最后,您需要将应用程序部署到一个Web服务器上,以便可以通过URL访问它。例如,您可以使用Tomcat或Jetty作为您的Web服务器。 请注意,以上代码仅用于示例目的,您需要根据您自己的需求进行修改和调整。同时,微信开放平台的API接口可能会随时更改,请确保您使用的是最新的API文档。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值