数据分析:微生物数据的荟萃分析框架

news2024/9/23 6:36:43

介绍

Meta-analysis of fecal metagenomes reveals global microbial signatures that are specific for colorectal cancer提供了一种荟萃分析的框架,它主要基于常用的Wilcoxon rank-sum test和Blocked Wilcoxon rank-sum test 方法计算显著性,再使用分位数计算分组间的倍数变化,最后通过AUC判断物种的区分分组的能力。最后通过热图和森林图展示筛选到的在不同研究和荟萃分析均有差异的物种。

该框架可用于同类型的微生物荟萃分析。

加载R包

#| warning: false
#| message: false

library(tidyverse)
library(readr)
library(coin)
library(pROC)
library(RColorBrewer)
library(cowplot)

# rm(list = ls())
options(stringsAsFactors = F)
options(future.globals.maxSize = 1000 * 1024^2)

导入数据

数据下载百度云盘链接: https://pan.baidu.com/s/1VS6S8p5s20vwZ6FyILYoaQ

提取码: g4y3

  • 物种表达谱数据

  • 样本分组信息

#| warning: false
#| message: false

feat.all <- read.table("./data/meta-CRC-2019/feat_rel_crc.tsv", 
                       sep='\t', header=TRUE, 
                       stringsAsFactors = FALSE, 
                       check.names = FALSE, quote='') %>%
  as.matrix()

meta <- read_tsv('./data/meta-CRC-2019/meta_crc.tsv', show_col_types = FALSE)
  • 其他参数(过滤和检验结果)
#| warning: false
#| message: false

alpha.meta <- 1e-05
alpha.single.study <- 0.005
mult.corr <- 'fdr'
pr.cutoff <- 0.05
log.n0 <- 1e-05
log.n0.func <- 1e-08
study.cols <- c('#2FBFBF', '#177254', '#F2CC30', '#74B347', '#8265CC')

数据预处理

  • 提出研究名称studies

  • 设置block分组,用于后续检验

#| warning: false
#| message: false

studies <- meta %>% 
  dplyr::pull(Study) %>% 
  unique

# block for colonoscopy and study as well
meta <- meta %>%
  dplyr::filter(!is.na(Sampling_rel_to_colonoscopy)) %>%
  dplyr::mutate(block = ifelse(Study != 'CN-CRC', Study, 
        paste0(Study, '_', Sampling_rel_to_colonoscopy)))

feat.all <- feat.all[, meta$Sample_ID]

荟萃分析

荟萃分析采用了Wilcoxon rank-sum test和Blocked Wilcoxon rank-sum test 两种方法对单个研究和合并所有研究做显著性检验。本次需要计Foldchange(FC)单个研究的pvalue + 所有研究的pvalue(p.val)单个研究和所有研究的AUC(aucs),以下是该代码的计算过程:

  • 先使用Wilcoxon rank-sum test计算每个研究的每个物种在case/control之间的显著性检验结果;

  • 再通过roc函数计算每个研究的每个物种在case/control之间的判别效果;

  • 接着通过分位数quantile计算每个研究的每个物种在case/control之间的倍数变化;

  • 然后通过Blocked Wilcoxon rank-sum test计算所有研究的荟萃差异检验结果;

  • 最后计算所有研究的平均倍数变化作为整体倍数变化和通过roc函数计算每个物种在case/control之间的判别效果。

#| warning: false
#| message: false

p.val <- matrix(NA, nrow = nrow(feat.all), ncol = length(studies)+1, 
                dimnames = list(row.names(feat.all), c(studies, 'all')))
fc <- p.val
aucs.mat <- p.val
aucs.all <- vector('list', nrow(feat.all))

cat("Calculating effect size for every feature...\n")
pb <- txtProgressBar(max = nrow(feat.all), style = 3)

# caluclate wilcoxon test and effect size for each feature and study
for (f in row.names(feat.all)) {
  
  # for each study
  for (s in studies) {
    
    x <- feat.all[f, meta %>% dplyr::filter(Study == s) %>% 
                    dplyr::filter(Group=='CRC') %>% dplyr::pull(Sample_ID)]
    y <- feat.all[f, meta %>% dplyr::filter(Study==s) %>% 
                    dplyr::filter(Group=='CTR') %>% dplyr::pull(Sample_ID)]
    
    # Wilcoxon: 对单个研究的单个物种检验
    p.val[f, s] <- wilcox.test(x, y, exact=FALSE)$p.value
    
    # AUC:评估每个物种区分分组的能力
    aucs.all[[f]][[s]] <- c(roc(controls=y, cases=x, 
                                direction='<', ci=TRUE, auc=TRUE)$ci)
    aucs.mat[f, s] <- c(roc(controls=y, cases=x, 
                           direction='<', ci=TRUE, auc=TRUE)$ci)[2]
    
    # FC:使用10分位数计算每个物种的相对丰度再计算Foldchange结果
    q.p <- quantile(log10(x+log.n0), probs = seq(.1, .9, .05))
    q.n <- quantile(log10(y+log.n0), probs = seq(.1, .9, .05))
    fc[f, s] <- sum(q.p - q.n)/length(q.p)
  }
  
  # calculate effect size for all studies combined
  # Wilcoxon + blocking factor:计算所有研究混合在一起的检验结果
  d <- data.frame(y = feat.all[f,], 
                  x = meta$Group, 
                  block = meta$block) %>%
    dplyr::mutate(x = factor(x),
                  block = factor(block))
  p.val[f, 'all'] <- coin::pvalue(wilcox_test(y ~ x | block, data = d))
  # other metrics
  x <- feat.all[f, meta %>% dplyr::filter(Group=='CRC') %>% dplyr::pull(Sample_ID)]
  y <- feat.all[f, meta %>% dplyr::filter(Group=='CTR') %>% dplyr::pull(Sample_ID)]
  # FC: 取所有样本的平均FC结果
  fc[f, 'all'] <- mean(fc[f, studies])
  # AUC:合并数据集每个物种区分不同分组样本的能力
  aucs.mat[f, 'all'] <- c(roc(controls=y, cases=x, 
                             direction='<', ci=TRUE, auc=TRUE)$ci)[2]
  
  # progressbar
  setTxtProgressBar(pb, (pb$getVal()+1))
}
cat('\n')

# multiple hypothesis correction
p.adj <- data.frame(apply(p.val, MARGIN=2, FUN=p.adjust, method=mult.corr),
                    check.names = FALSE)

查看结果

查看上述荟萃分析的结果

#| warning: false
#| message: false

head(p.adj)

head(aucs.mat)

head(fc)

画图

文章给出的图分成两部分,上部分是热图形式,下半部是森林图。

  • 热图: 展示不同研究显著差异的物种
#| warning: false
#| message: false

species.heatmap <- rownames(p.adj)[which(p.adj$all < alpha.single.study)]

fc.sign <- sign(fc)
fc.sign[fc.sign == 0] <- 1

p.val.signed <- -log10(p.adj[species.heatmap,"all", drop=FALSE]) * 
  fc.sign[species.heatmap, 'all']

top.markers <- rownames(p.val.signed[is.infinite(p.val.signed$all) , , drop=FALSE])
p.val.signed[top.markers, 'all'] <- 100 + aucs.mat[top.markers, 'all']

species.heatmap.orderd <- rownames(p.val.signed[order(p.val.signed$all), , drop=FALSE])

# take only those
fc.mat.plot <- fc[species.heatmap.orderd, ] %>% as.data.frame()
p.vals.plot <- p.adj[species.heatmap.orderd, ]

# ##############################################################################
# prepare plotting

# colorscheme for fc heatmap 
mx <- max(abs(range(fc.mat.plot, na.rm=TRUE)))
mx <- ifelse(round(mx, digits = 1) < mx, 
             round(mx, digits = 1) + 0.1, 
             round(mx, digits = 1))
brs <- seq(-mx, mx, by=0.05)
num.col.steps <- length(brs) - 1
n <- floor(0.45*num.col.steps)
col.hm <- c(rev(colorRampPalette(brewer.pal(9, 'Blues'))(n)),
           rep('#FFFFFF', num.col.steps-2*n),
           colorRampPalette(brewer.pal(9, 'Reds'))(n))
# color scheme for pval heatmap
alpha.breaks <- c(1e-06, 1e-05, 1e-04, 1e-03, 1e-02, 1e-01)
p.vals.bin <- data.frame(apply(p.vals.plot, 2, FUN=.bincode, 
                               breaks = c(0, alpha.breaks, 1), 
                               include.lowest = TRUE),
                         check.names = FALSE)
p.val.greys <- c(paste0('grey', 
                         round(seq(from=10, to=80, 
                                   length.out = length(alpha.breaks)))), 
                  'white')
names(p.val.greys) <- as.character(1:7)

# function to plot both into a grid
plot.single.study.heatmap <- function(x) {
  
  # x = "FR-CRC"
  
  df.plot <- tibble(species = factor(rownames(p.vals.plot), 
                                   levels = rev(rownames(p.vals.plot))),
                    p.vals = as.factor(p.vals.bin[[x]]),
                    fc = fc.mat.plot[[x]])
  
  g1 <- df.plot %>% 
    ggplot(aes(x = species, y = 1, fill = fc)) + 
      geom_tile() + theme_minimal() + 
      theme(axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title = element_blank(), 
            panel.grid = element_blank(),
            panel.background = element_rect(fill=NULL, colour='black'),
            plot.margin = unit(c(0, 0, 0, 0), 'cm')) + 
      scale_y_continuous(expand = c(0, 0)) + 
      scale_fill_gradientn(colours=col.hm, limits=c(-mx, mx), guide=FALSE)
  
  g2 <- df.plot %>% 
    ggplot(aes(x=species, y=1, fill=p.vals)) +
      geom_tile() + theme_minimal() + 
      theme(axis.text = element_blank(),
            axis.ticks = element_blank(),
            axis.title = element_blank(), 
            panel.grid = element_blank(),
            panel.background = element_rect(fill=NULL, colour='black'),
            plot.margin = unit(c(0, 0, 0, 0), 'cm')) + 
      scale_y_continuous(expand = c(0, 0)) + 
      scale_fill_manual(values=p.val.greys, na.value='white', guide=FALSE)
  
  g.return <- plot_grid(g2, g1, ncol = 1, rel_heights = c(0.25, 0.75))
  
  return(g.return)
}

# ##############################################################################
# plot

# p.value histogram
g1 <- tibble(species = factor(rownames(p.vals.plot), 
                            levels = rev(rownames(p.vals.plot))),
             p.vals = -log10(p.vals.plot$all),
             colour = p.vals > 5) %>% 
  ggplot(aes(x = species, y = p.vals, fill = colour)) + 
    geom_bar(stat = 'identity') + 
    theme_classic() + 
    xlab('Gut microbial species') + 
    ylab('-log10(q-value)') + 
    theme(panel.grid.major = element_blank(),
          panel.grid.minor = element_blank(),
          axis.ticks.x = element_blank(),
          axis.text.x = element_blank(),
          panel.background = element_rect(fill = NULL, color = 'black')) + 
    scale_y_continuous(limits = c(0, 15), expand = c(0, 0)) + 
    scale_x_discrete(position = 'top') + 
    scale_fill_manual(values = c('lightgrey', 'darkgrey'), guide = FALSE)

g.lst <- lapply(studies, plot.single.study.heatmap)

pl1 <- plot_grid(g1, g.lst[[1]], g.lst[[2]], 
          g.lst[[3]], g.lst[[4]],g.lst[[5]], 
          ncol = 1, align = 'v', 
          rel_heights = c(0.3, rep(0.12, 5)))

pl1

结果:差异物种在不同研究和整合数据的倍数变化和显著性结果

  • 最上图是物种在整合数据的显著性结果(adjustedPvalue);

  • 接下来的热图是物种在单个研究的显著性结果(上半部)和倍数变化(下半部:红色是富集在CRC,蓝色是CTRL);

  • 森林图: 不同物种在每个研究区分case/control的能力 (通过alpha.meta更严格筛选)

#| warning: false
#| message: false

# select and order
marker.set <- rownames(p.val.signed)[
  abs(p.val.signed$all) > -log10(alpha.meta)]
p.val.signed.red <- p.val.signed[marker.set, ,drop=FALSE]
marker.set.orderd <- rev(rownames(p.val.signed.red[order(p.val.signed.red$all),,
                                               drop=FALSE]))

# extract those from the auc list
df.plot <- tibble()
for (i in marker.set.orderd){
  for (s in studies){
    temp <- aucs.all[[i]][[s]]
    df.plot <- bind_rows(df.plot, tibble(
      species=i, study=s,
      low=temp[1], auc=temp[2], high=temp[3]
    ))
  }
}

df.plot <- df.plot %>% 
  dplyr::mutate(species = factor(species, levels = marker.set.orderd)) %>% 
  dplyr::mutate(study = factor(study, levels = studies))

# plot everything
pl2 <- df.plot %>% 
  ggplot(aes(x = study, y = auc)) + 
    geom_linerange(aes(ymin = low, ymax = high), color = 'lightgrey') + 
    geom_point(pch = 23, aes(fill = study)) + 
    facet_grid(~species, scales = 'free_x', space = 'free') + 
    theme_minimal() + 
    scale_y_continuous(limits=c(0, 1)) + 
    theme(panel.grid.major.x = element_blank(),
          axis.ticks.x = element_blank(),
          axis.text.x = element_blank(),
          strip.text = element_text(angle=90, hjust=0)) + 
    scale_fill_manual(values = study.cols, 
                      guide = FALSE) + 
    ylab('AUROC') + xlab('Gut microbial species')

pl2

  • 合并图: 最后文章呈现的图是经过修改的
#| warning: false
#| message: false

cowplot::plot_grid(pl1, pl2, ncol = 1)

总结

在进行荟萃分析时,本研究采用了一种特定的统计方法——Blocked Wilcoxon rank-sum test,以评估和整合不同研究中的case/control物种的显著性结果。该方法特别适用于处理微生物数据这类稀疏性数据集,因为它能够在计算两组之间的倍数变化时有效避免零值过多的问题。通过使用分位数方法,研究者能够更准确地估计和比较不同组之间的差异,从而提高了分析结果的可靠性和有效性。

对于类似类型的研究,研究者可以采用与本研究相似的分析框架进行荟萃分析。这包括以下几个关键步骤:

  • 数据的收集与整理:确保收集到的数据是高质量的,并且适合进行荟萃分析。
  • 选择合适的统计方法:根据数据的特点选择合适的统计检验方法,如Blocked Wilcoxon rank-sum test,以确保分析的准确性。
  • 数据处理:对于稀疏数据,采用分位数方法来处理零值过多的问题,以提高分析的稳健性。
  • 结果的整合与解释:将不同研究的结果进行整合,并采用适当的统计方法来评估整体的显著性。

通过遵循这样的框架,研究者可以对类似主题的研究进行系统性地分析和比较,从而为该领域的研究提供更深入的见解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1942989.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STM32自己从零开始实操10:PCB全过程

一、PCB总体分布 分布主要参考有&#xff1a; 方便供电布线。方便布信号线。方便接口。人体工学。 以下只能让大家看到各个模块大致分布在板子的哪一块&#xff0c;只能说每个人画都有自己的理由&#xff0c;我的理由如下。 还有很多没有表达出来的东西&#xff0c;我也不知…

Python和MATLAB网络尺度结构和幂律度大型图生成式模型算法

&#x1f3af;要点 &#x1f3af;算法随机图模型数学概率 | &#x1f3af;图预期度序列数学定义 | &#x1f3af;生成具有任意指数的大型幂律网络&#xff0c;数学计算幂律指数和平均度 | &#x1f3af;随机图分析中巨型连接分量数学理论和推论 | &#x1f3af;生成式多层网络…

如何解决Windows系统目录权限问题

目录 前言1. 为什么会出现权限问题2. 修改文件权限的步骤2.1 确定目标文件2.2 右键属性设置2.3 更改所有者2.4 修改权限2.5 确认修改 3. 替换文件3.1 拷贝新的文件3.2 验证替换结果 结语 前言 在Windows系统中&#xff0c;时常需要往C盘系统目录下拷贝或者替换文件。然而&…

【Python系列】JSON 序列化性能对比分析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【学术会议征稿】第五届计算机工程与智能通信国际研讨会(ISCEIC 2024)

第五届计算机工程与智能通信国际研讨会&#xff08;ISCEIC 2024&#xff09; 2024 5th International Symposium on Computer Engineering and Intelligent Communications (ISCEIC 2024) 第五届计算机工程与智能通信国际研讨会&#xff08;ISCEIC 2024&#xff09;将于2024年…

安全管理(EHS系统)是什么?化工企业如何进行安全管理?

化工企业一般会涉及到易燃易爆、有毒有害的原材料和产品&#xff0c;生产环境有高温高压、腐蚀性强等危险因素。一旦管理不善或操作失误&#xff0c;极易引发火灾、爆炸、中毒等严重事故&#xff0c;不仅有人身伤害&#xff0c;还会给企业带来巨大损失&#xff0c;甚至影响社会…

如何快速批量修改照片拍摄日期?一键批量搞定拍摄日期修改教程

在摄影爱好者、专业摄影师甚至普通用户中&#xff0c;照片不仅仅是视觉记录&#xff0c;它们还承载着时间和地点的印记。当需要调整大量照片的拍摄日期时&#xff0c;手动操作显然不是最高效的方法。幸运的是&#xff0c;现代文件管理工具如“简鹿文件批量重命名”软件提供了批…

数据隐私保护与区块链技术的结合:新兴趋势分析

在当今数字化时代&#xff0c;数据隐私保护成为了一个备受关注的重要话题。随着个人数据的不断生成和流通&#xff0c;如何有效保护用户的隐私成为了技术创新的一个重要方向。区块链技术作为一种去中心化、安全性高且可追溯的技术手段&#xff0c;正在逐渐成为解决数据隐私保护…

Android --- 广播

广播是什么&#xff1f; 一种相互通信&#xff0c;传递信息的机制&#xff0c;组件内、进程间&#xff08;App之间&#xff09; 如何使用广播&#xff1f; 组成部分 发送者-发送广播 与启动其他四大组件一样&#xff0c;广播发送也是使用intent发送。 设置action&#xff…

RoundCube搭建安装教程:服务器配置方法?

RoundCube搭建安装教程的疑问解析&#xff01;怎么搭建邮件系统&#xff1f; RoundCube是一款开源的Web邮件客户端&#xff0c;具有现代化的用户界面和丰富的功能&#xff0c;可以通过浏览器访问邮件服务器。AokSend将详细介绍如何在服务器上配置和安装RoundCube&#xff0c;以…

JS语法学习

找到官方库&#xff0c;查看相应资料&#xff1a;&#xff08;都可以切换为中文版本的&#xff09; 可以在 JavaScript 的官方网站上查看最新的语法规范和文档。JavaScript 的官方网站是 developer.mozilla.orghttps://developer.mozilla.org/en-US/docs/Web/JavaScript。那里…

尚庭公寓开发笔记(一)

本篇文章讲的是p前五十节课 可以关注后续 传统的数据库设计流程 分为三个阶段&#xff1a;概念模型设计阶段 逻辑模型设计阶段 物理模型设计 阶段 为本项目设计数据库模型 地图的存储只需要保存经纬度就ok 本项目采用的是mysql数据库 所有表都使用的是innnodb存储引擎 我们使…

数据编织 VS 数据仓库 VS 数据湖

目录 1. 什么是数据编织?2. 数据编织的工作原理3. 代码示例4. 数据编织的优势5. 应用场景6. 数据编织 vs 数据仓库6.1 数据存储方式6.2 数据更新和实时性6.3 灵活性和可扩展性6.4 查询性能6.5 数据治理和一致性6.6 适用场景6.7 代码示例比较 7. 数据编织 vs 数据湖7.1 数据存储…

内网安全:IPC横向

IPC计划任务横向 IPC配合系统服务横向 前言&#xff1a; IPC是为了实现进程之间的通信而开放的管道。IPC可以通过验证用户名和密码来获取相应的权限。通过IPC可以与目标机器建立连接。 IPC计划任务横向 本次目标&#xff1a;通过机器192.168.11.40&#xff0c;横向控制机器192…

dependency-check-maven依赖漏洞扫描

引入插件依赖&#xff1a; <plugin><groupId>org.owasp</groupId><artifactId>dependency-check-maven</artifactId><version>7.0.4</version><configuration><autoUpdate>false</autoUpdate><dataDirectory&g…

SQL

SQL全称 Structured Query Language&#xff0c;结构化查询语言。操作关系型数据库的编程语言&#xff0c;定义了一套操作关系型数据库统一标准 。 SQL通用语法 SQL语句可以单行或多行书写&#xff0c;以分号结尾。SQL语句可以使用空格/缩进来增强语句的可读性。MySQL数据库的…

bug诞生记——动态库加载错乱导致程序执行异常

大纲 背景问题发生问题猜测和分析过程是不是编译了本工程中的其他代码是不是有缓存是不是编译了非本工程的文件是不是调用了其他可执行文件查看CMakefiles分析源码检查正在运行程序的动态库 解决方案 这个案例发生在我研究ROS 2的测试Demo时发生的。 整体现象是&#xff1a;修改…

电脑突然出现‘vcruntime140_1.dll无法继续执行代码’的问题正确处理方法

如果你的电脑出现vcruntime140_1.dll无法继续执行代码的提示&#xff0c;那么你就要重视这个问题了&#xff0c;因为这代表vcruntime140_1.dll文件有可能损坏了或者找不到了&#xff0c;一旦这个vcruntime140_1.dll文件不见了&#xff0c;那么你的很多程序都会打不开&#xff0…

CatBoost模型Python代码——用CatBoost模型实现机器学习

一、CatBoost模型简介 1.1适用范围 CatBoost&#xff08;Categorical Boosting&#xff09;是一种基于梯度提升的机器学习算法&#xff0c;特别适用于处理具有类别特征的数据集。它可以用于分类、回归和排序任务&#xff0c;并且在处理具有大量类别特征的数据时表现优异。典型…

FPGA:3-8译码器的设计

1、什么是3-8译码器&#xff1f; 3-8译码器&#xff0c;顾名思义&#xff0c;三个输入&#xff0c;八个输出&#xff0c;构成3-8译码器。根据二进制特性&#xff0c;三位二进制数有八种可能&#xff0c;对应的真值表如下所示(该译码器输出低电平有效)&#xff1a; 3-8译码器(…