冗余分析简介
什么是RDA分析?
RDA分析(Redundancy Analysis, 冗余分析),是环境因子约束化的PCA分析,可以将样本和环境因子反映在同一个二维排序图上,从图中可以直观地看出样本分布和环境因子间的关系。从概念上讲,RDA是响应变量矩阵与解释变量矩阵之间多元多重线性回归的拟合值矩阵的PCA分析,也是多响应变量回归分析的拓展。在群落分析中常使用RDA,将物种多度的变化分解为与环境变量相关的方差,用以探索群落物种组成受环境变量的约束关系。
什么是tb-RDA?
包含很多零值的物种多度数据在执行多元回归或其它基于欧氏距离的分析方法之前必须被转化,tb-RDA(基于转化的RDA)被提出用于解决这个问题。tb-RDA在分析前首先对原始数据做一定的转换,并使用转化后的数据执行RDA。即除了第一步增添了数据转化外,其余过程均和常规的RDA相同,只是在原始数据本身做了改动,RDA算法本质未变。
什么是偏冗余分析?
偏冗余分析(Partial canonical ordination, 偏RDA)相当于多元偏线性回归分析,在实际应用中同样广泛。在解释变量的向前选择过程中,偏RDA应用广泛。
什么是基于距离的冗余分析(db-RDA)?
尽管tb-RDA的应用拓展了RDA的适应范围,但无论常规的RDA或tb-RDA,样方或物种的降维过程实质上均以欧氏距离为举出。有时候我们可能期望关注非欧式距离样方或物种关系的RDA,。基于距离的冗余分析被提出用于解决这个问题,并且证明RDA能够以方差分析方式分析由用于选择的任何距离矩阵。db-RDA将主坐标分析(PCoA)计算的样方得分矩阵应用在RDA中,其好处是可以基于任意一种距离测度进行RDA排序,因此db-RDA在生态学统计分析中被广泛使用。db-RDA首先基于物种多度数据计算相异矩阵,作为PCoA的输入,之后将所有PCoA排序轴上的样方得分矩阵用于执行RDA,而不再使用原始的物种数据以及解释变量直接作为RDA的输入。由于在PCoA中可能会产生负特征值,必要时需要引入一些有效的矫正方法。尽管物种信息在相异矩阵的计算过程中丢失,但柱坐标矩阵依然可以视为表征数据总方差的距离矩阵,因此db-RDA结果反映了解释变量对从整个响应数据中得出的样方相似性的隐形。物种得分可以通过与它们所在样方得分的多度加权平均与PCoA轴建立关联而投影到最终的排序图中,用以表明响应变量对PCoA排序的贡献程度。
标签:#微生物组数据分析 #MicrobiomeStatPlot #冗余分析图 #R语言可视化 #dbRDA
作者:First draft(初稿):Defeng Bai(白德凤);Proofreading(校对):Ma Chuang(马闯) and Jiani Xun(荀佳妮);Text tutorial(文字教程):Defeng Bai(白德凤)
源代码及测试数据链接:
https://github.com/YongxinLiu/MicrobiomeStatPlot/项目中目录 3.Visualization_and_interpretation/dbRDAplot
或公众号后台回复“MicrobiomeStatPlot”领取
这是来自于加州大学洛杉矶分校的Emeran A. Mayer团队在2023年发表于Microbiome上的一篇论文用到的dbRDA图。论文题目为:Multi-omics profles of the intestinal microbiome in irritable bowel syndrome and its bowel habit subtypes.https://doi.org/10.1186/s40168-022-01450-5
图 1 | IBS与微生物组组成和功能的全面改变有关。
图 1 (C) 进行基于距离的冗余分析 (dbRDA),以可视化与 IBS 状态、年龄、性别、种族/民族、BMI、饮食类别和 HAD-焦虑 (HAD-A) 相关的 beta 多样性变化。IBS 组和具有统计学意义的分类变量用字母或符号表示,表示每个类别的质心。具有统计学意义的连续变量显示为源自所有样本质心的箭头,长度与关联强度成正比。F = 女性,M = 男性,A = 亚裔,B = 非裔美国人,H = 西班牙裔,W = 非西班牙裔白人,R = 多种族。
结果
发现许多协变量与一个或两个数据集中的微生物组成显著相关,包括年龄、性别、种族、BMI、饮食类别、HAD-焦虑和 HAD 抑郁。鉴于焦虑和抑郁之间的强相关性以及 HAD-焦虑中 IBS 和 HC 之间的较大差异,因此将其选为协变量来表示情绪与微生物组的关联。在调整这些协变量的多变量分析中,IBS 仍然与 16S rRNA 和宏转录组测序的微生物组成显著相关,年龄和种族等几个协变量也是如此(图 1B、C)。在协变量中,年龄、性别、种族、BMI、饮食类别和 HAD-Anxiety 与宏转录组和代谢组显著相关;年龄、种族和 BMI 也与预测的宏基因组显著相关。调整这六个协变量后,IBS 仍然与宏转录组和预测的宏基因组显著相关,但与代谢组不再具有显著关联(图 1B、C)。
源代码及测试数据链接:
https://github.com/YongxinLiu/MicrobiomeStatPlot/
或公众号后台回复“MicrobiomeStatPlot”领取
软件包安装
# 基于CRAN安装R包,检测没有则安装
p_list = c("vegan", "ggplot2", "ggpubr", "ggrepel", "rdacca.hp", "vegan", "psych", "reshape2")
for(p in p_list){if (!requireNamespace(p)){install.packages(p)}
library(p, character.only = TRUE, quietly = TRUE, warn.conflicts = FALSE)}
# 加载R包 Load the package
suppressWarnings(suppressMessages(library(vegan)))
suppressWarnings(suppressMessages(library(ggplot2)))
suppressWarnings(suppressMessages(library(ggpubr)))
suppressWarnings(suppressMessages(library(ggrepel)))
suppressWarnings(suppressMessages(library(rdacca.hp)))
微生物物种dbRDA分析Microbiota species
# 读入物种数据,以细菌 OTU 水平丰度表为例
otu = read.csv('data/species_data.csv', head = T, row.names=1)
otu <- data.frame(t(otu))
# 分组数据
matadata <- read.table(paste("data/group_data.txt",sep=""), header=T, row.names=1, sep="\t", comment.char="")
otu = otu[rownames(otu) %in% rownames(matadata), ]
# 读取环境数据
env = read.csv('data/c_index_species_new4.csv', header = T, row.names=1)
env = na.omit(env)
env = env[rownames(env) %in% rownames(matadata), ]
rownames = rownames(env)
rownames = as.data.frame(rownames)
otu$rownames = rownames(otu)
otu = merge(otu, rownames, by = "rownames")
rownames(otu) = otu$rownames
otu = otu[, -1]
# 根据原理一步步计算 db-RDA
# Calculate db-RDA step by step according to the principle
# 计算样方距离,以 Bray-curtis 距离为例,详情 ?vegdist
# Calculate the sample distance, taking Bray-curtis distance as an example, details ?vegdist
# dis_bray <- vegdist(otu, method = 'bray')
distance_mat = read.table(paste("data/Species_beta_diversity2.txt",sep=""), header=T, row.names=1, sep="\t", comment.char="")
metadata2 = t(matadata)
distance_mat2 = distance_mat[rownames(distance_mat) %in% rownames(matadata), ]
distance_mat3 = distance_mat2[, colnames(distance_mat2) %in% colnames(metadata2)]
distance_mat = distance_mat3
# 或者直接使用现有的距离矩阵,这里同样为 Bray-curtis 距离
# Or directly use the existing distance matrix, which is also the Bray-curtis distance
dis_bray <- as.dist(distance_mat)
# PCoA 排序,这里通过 add = TRUE校正负特征值,详情 ?cmdscale
# PCoA sorting, here add = TRUE is used to correct negative eigenvalues, details ?cmdscale
pcoa <- cmdscale(dis_bray, k = nrow(otu) - 1, eig = TRUE, add = TRUE)
# 提取 PCoA 样方得分(坐标)
# Extract PCoA sample scores (coordinates)
pcoa_site <- pcoa$point
# 通过 vegan 包的 RDA 函数 rda() 执行,详情 ?rda
# Execute via the RDA function rda() of the vegan package, details ?rda
db_rda <- rda(pcoa_site, env, scale = FALSE)
# 被动拟合物种得分
# Passive fitting species score
v.eig <- t(otu) %*% db_rda$CCA$u/sqrt(nrow(otu) - 1)
db_rda$CCA$v <- decostand(v.eig, 'normalize', MARGIN = 2)
v.eig <- t(otu) %*% db_rda$CA$u/sqrt(nrow(otu) - 1)
db_rda$CA$v <- decostand(v.eig, 'normalize', MARGIN = 2)
# 提取画图所需要的数据
# Extract the data needed for drawing
score = scores(db_rda)
db_rda$CCA$biplot
#> RDA1 RDA2 RDA3
#> status 0.76440409 -0.48475784 0.4250838
#> sex 0.98352818 0.17911294 -0.0243079
#> age -0.01213581 -0.06874258 -0.9975606
CAP1 = score$sites[,1]
CAP2 = score$sites[,2]
seg = as.data.frame(db_rda$CCA$biplot)
CPA_data = as.data.frame(score$sites)
CPA_data$group = rownames(CPA_data)
CPA_data$group = as.character(CPA_data$group)
CPA_data$group = gsub("[0-9]","", CPA_data$group)
# 将上述提取的数据整合成画图所需的表格
# Integrate the above extracted data into the table required for drawing
plotdata = data.frame(rownames(score$sites), CAP1, CAP2, CPA_data$group)
colnames(plotdata) = c('sample','CAP1','CAP2','Group') #为其加上列名(add column name)
# 计算第一、二主轴的解释度
# Calculate the explanation of the first and second principal axes
CAP1_exp = round(db_rda$CCA$eig[1]/sum(db_rda$CCA$eig)*100,2)
CAP2_exp = round(db_rda$CCA$eig[2]/sum(db_rda$CCA$eig)*100,2)
p1 = ggplot(plotdata, aes(CAP1, CAP2)) +
geom_point(aes(fill = Group, color = Group),size = 1.3) +
scale_fill_manual(values = c("#74add1","#a60026"))+
scale_color_manual(values = c("#74add1","#a60026"))+
#添加置信区间,两种选一个就行
#stat_ellipse(linetype = 1,level = 0.95,aes(group = Treatment, color = Treatment)) +
#stat_chull(geom = 'polygon', aes(group = Treatment, color = Treatment, fill = Treatment), alpha = 0.1) +
xlab(paste('dbRDA1 ( ',CAP1_exp,'%',' )', sep = '')) +
ylab(paste('dbRDA2 ( ',CAP2_exp,'%',' )', sep = '')) +
geom_segment(data = seg, aes(x = 0, y = 0, xend = seg[,1], yend = seg[,2]),
colour = "red", size = 0.3,
arrow = arrow(angle = 30, length = unit(0.4, 'cm'))) +
geom_text_repel(data = seg, segment.colour = 'black',
aes(x = seg[,1], y = seg[,2],
label = rownames(seg)),size = 3) +
geom_vline(aes(xintercept = 0), linetype = 'dotted') +
geom_hline(aes(yintercept = 0), linetype = 'dotted') +
theme_bw()+
theme(text = element_text(family = 'sans', size = 12),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
,legend.position = 'none'
)+
theme(axis.text = element_text(colour = 'black',size = 12))+
stat_ellipse(
level=0.95,
linetype = 2,size=0.7,
aes(color=Group),
alpha=0.8)+
coord_equal(ratio=0.9)
ggsave(paste("results/dbRDA_Species01.pdf",".pdf", sep=""), p1, width=149 * 1.5, height=80 * 1.5, unit='mm')
#p1
# 置换检验
# Permutation test
env$status = as.numeric(env$status)
env$sex = as.vector(env$sex)
env$age = as.vector(env$age)
envfit <- envfit(db_rda, env, permutations = 999)
r <- as.matrix(envfit$vectors$r)
p <- as.matrix(envfit$vectors$pvals)
env.p <- cbind(r,p)
colnames(env.p) <- c("r2","p-value")
KK <- as.data.frame(env.p)
KK$p.adj = p.adjust(KK$`p-value`, method = 'BH')
# KK
# 利用rdacca.hp计算每个环境因子的效应
# Use rdacca.hp to calculate the effect of each environmental factor
dis_bray <- as.dist(distance_mat)
bray = dis_bray
cap.hp = rdacca.hp(bray, env, method = 'dbRDA', type = 'R2', scale = FALSE)
cap.hp$Total_explained_variation
#> [1] 0.204
cap.hp$Hier.part
#> Unique Average.share Individual I.perc(%)
#> status 0.0760 -0.0009 0.0751 36.81
#> sex 0.0788 0.0026 0.0814 39.90
#> age 0.0539 -0.0063 0.0476 23.33
# 导出每个环境因子的解释度
# Export the explanation of each environmental factor
# Unique:每个解释变量单独解释的总变化量的比例,即与其它解释变量不存在共存解释的部分
# Unique: The proportion of the total variation explained by each explanatory variable alone, that is, the part that does not coexist with other explanatory variables
# Average.share: 对每个解释变量与其它解释变量共同解释部分的分割
# Average.share: Split each explanatory variable into its common explanation with other explanatory variables
# Individual: 每个解释变量站总变化量的比例Individual等于Unique和Average.share的总和
# Individual: The proportion of the total variation of each explanatory variable station is equal to the sum of Unique and Average.share
# I.prec(%): 每个解释变量占总被解释变化量的比例,即各解释变量的Individual占Individual总和的百分比,Individual总和等同db-RDA的总解释方差占比
# I.prec(%): The proportion of each explanatory variable to the total explained variance, that is, the percentage of each explanatory variable's individual to the individual sum, and the individual sum is equivalent to the total explained variance proportion of db-RDA
功能通路Pathways
# 读取数据
# 读入物种数据,以细菌 OTU 水平丰度表为例
otu = read.csv('data/pathway_unstrafied4.csv', head = T, row.names=1) #读取物种相对丰度表
otu <- data.frame(t(otu))
# 分组数据
matadata <- read.table(paste("data/group_data.txt",sep=""), header=T, row.names=1, sep="\t", comment.char="")
otu = otu[rownames(otu) %in% rownames(matadata), ]
# 读取环境数据
env = read.csv('data/c_index_species_new4.csv', header = T, row.names=1)
env = na.omit(env)
env = env[rownames(env) %in% rownames(matadata), ]
rownames = rownames(env)
rownames = as.data.frame(rownames)
otu$rownames = rownames(otu)
otu = merge(otu, rownames, by = "rownames")
rownames(otu) = otu$rownames
otu = otu[, -1]
# Bray-curtis distance
# Pathways
distance_mat = read.table(paste("data/bray_curtis_path3.txt",sep=""), header=T, row.names=1, sep="\t", comment.char="")
metadata2 = t(matadata)
distance_mat2 = distance_mat[rownames(distance_mat) %in% rownames(matadata), ]
distance_mat3 = distance_mat2[, colnames(distance_mat2) %in% colnames(metadata2)]
distance_mat = distance_mat3
# 或者直接使用现有的距离矩阵,这里同样为 Bray-curtis 距离
# Or directly use the existing distance matrix, which is also the Bray-curtis distance
dis_bray <- as.dist(distance_mat)
# PCoA 排序,这里通过 add = TRUE校正负特征值,详情 ?cmdscale
# PCoA sorting, here add = TRUE is used to correct negative eigenvalues, details ?cmdscale
pcoa <- cmdscale(dis_bray, k = nrow(otu) - 1, eig = TRUE, add = TRUE)
# 提取 PCoA 样方得分(坐标)
# Extract PCoA sample scores (coordinates)
pcoa_site <- pcoa$point
# 通过 vegan 包的 RDA 函数 rda() 执行,详情 ?rda
# Execute via the RDA function rda() of the vegan package, details ?rda
db_rda <- rda(pcoa_site, env, scale = FALSE)
# 被动拟合物种得分
# Passive fitting species score
v.eig <- t(otu) %*% db_rda$CCA$u/sqrt(nrow(otu) - 1)
db_rda$CCA$v <- decostand(v.eig, 'normalize', MARGIN = 2)
v.eig <- t(otu) %*% db_rda$CA$u/sqrt(nrow(otu) - 1)
db_rda$CA$v <- decostand(v.eig, 'normalize', MARGIN = 2)
# 提取画图所需要的数据
# Extract the data needed for drawing
score = scores(db_rda)
db_rda$CCA$biplot
#> RDA1 RDA2 RDA3
#> status 0.8611765 0.47808765 -0.17264755
#> sex 0.6074361 -0.01168604 -0.79428262
#> age 0.1040567 -0.99010545 0.09414559
CAP1 = score$sites[,1]
CAP2 = score$sites[,2]
seg = as.data.frame(db_rda$CCA$biplot)
CPA_data = as.data.frame(score$sites)
CPA_data$group = rownames(CPA_data)
CPA_data$group = as.character(CPA_data$group)
CPA_data$group = gsub("[0-9]","", CPA_data$group)
# 将上述提取的数据整合成画图所需的表格
# Integrate the above extracted data into the table required for drawing
plotdata = data.frame(rownames(score$sites), CAP1, CAP2, CPA_data$group)
colnames(plotdata) = c('sample','CAP1','CAP2','Group') #为其加上列名(add column name)
# 计算第一、二主轴的解释度
# Calculate the explanation of the first and second principal axes
CAP1_exp = round(db_rda$CCA$eig[1]/sum(db_rda$CCA$eig)*100,2)
CAP2_exp = round(db_rda$CCA$eig[2]/sum(db_rda$CCA$eig)*100,2)
p2 = ggplot(plotdata, aes(CAP1, CAP2)) +
geom_point(aes(fill = Group, color = Group),size = 1.3) +
scale_fill_manual(values = c("#74add1","#a60026"))+
scale_color_manual(values = c("#74add1","#a60026"))+
#添加置信区间,两种选一个就行
#stat_ellipse(linetype = 1,level = 0.95,aes(group = Treatment, color = Treatment)) +
#stat_chull(geom = 'polygon', aes(group = Treatment, color = Treatment, fill = Treatment), alpha = 0.1) +
xlab(paste('dbRDA1 ( ',CAP1_exp,'%',' )', sep = '')) +
ylab(paste('dbRDA2 ( ',CAP2_exp,'%',' )', sep = '')) +
geom_segment(data = seg, aes(x = 0, y = 0, xend = seg[,1], yend = seg[,2]),
colour = "red", size = 0.3,
arrow = arrow(angle = 30, length = unit(0.4, 'cm'))) +
geom_text_repel(data = seg, segment.colour = 'black',
aes(x = seg[,1], y = seg[,2],
label = rownames(seg)),size = 3) +
geom_vline(aes(xintercept = 0), linetype = 'dotted') +
geom_hline(aes(yintercept = 0), linetype = 'dotted') +
theme_bw()+
theme(text = element_text(family = 'sans', size = 12),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
,legend.position = 'none'
)+
theme(axis.text = element_text(colour = 'black',size = 12))+
stat_ellipse(
level=0.95,
linetype = 2,size=0.7,
aes(color=Group),
alpha=0.8)+
coord_equal(ratio=0.4)
ggsave(paste("results/dbRDA_PATHs01.pdf",".pdf", sep=""), p2, width=149 * 1.5, height=80 * 1.5, unit='mm')
#p2
# 置换检验
# Permutation test
env$status = as.numeric(env$status)
env$sex = as.vector(env$sex)
env$age = as.vector(env$age)
envfit <- envfit(db_rda, env, permutations = 999)
r <- as.matrix(envfit$vectors$r)
p <- as.matrix(envfit$vectors$pvals)
env.p <- cbind(r,p)
colnames(env.p) <- c("r2","p-value")
KK <- as.data.frame(env.p)
KK$p.adj = p.adjust(KK$`p-value`, method = 'BH')
# KK
# 通过 vegan 包的 RDA 函数 rda() 执行,详情 ?rda
# Execute the RDA function rda() of the vegan package, see ?rda for details
# db_rda <- rda(pcoa_site~., env, scale = FALSE)
# RsquareAdj(rda(pcoa_site ~ status, data=env))$adj.r.squared
# RsquareAdj(rda(pcoa_site ~ status+sex, data=env))$adj.r.squared
# RsquareAdj(rda(pcoa_site ~ status+sex+age, data=env))$adj.r.squared
# 利用rdacca.hp计算每个环境因子的效应
# Use rdacca.hp to calculate the effect of each environmental factor
#dis_bray <- as.dist(distance_mat)
bray = dis_bray
cap.hp = rdacca.hp(bray, env, method = 'dbRDA', type = 'R2', scale = FALSE)
cap.hp$Total_explained_variation
#> [1] 0.08
cap.hp$Hier.part
#> Unique Average.share Individual I.perc(%)
#> status 0.0381 0.0046 0.0427 53.38
#> sex 0.0078 0.0082 0.0160 20.00
#> age 0.0254 -0.0037 0.0217 27.12
# 导出每个环境因子的解释度
# Export the explanation of each environmental factor
write.csv(cap.hp$Hier.part, 'results/env_effect_HP_new_paths_04.csv')
变异解释度热图
# Load data
allnew <- read.csv('data/data_heat_4.csv', header = T)
allnew[which(allnew$p<0.001),'sig'] <- '***'
allnew[which(allnew$p<0.01 & allnew$p>=0.001),'sig'] <- '**'
allnew[which(allnew$p<0.05 & allnew$p>=0.01),'sig'] <- '*'
allnew = allnew %>%
mutate(variable = ordered(variable,
levels=c("Species", "Pathways")))
# Plot
p3 <- ggplot(allnew, aes(variable,names, fill = deviance_explained)) +
geom_tile(aes(width = 1, height = 1), size = 12) +
geom_text(aes(label=deviance_explained), color="black", size=4) +
geom_text(aes(label=sig), color="black", size=8,vjust = 1.6) +
scale_fill_gradient2(low = "#afaa80", mid = "#e4cac6", high = "#5196d5",limit=c(0,1), breaks = seq(0, 0.25, 1)) +
theme(
panel.grid = element_blank(),
panel.background = element_blank(),
legend.title = element_text(angle = -90, hjust = 0.2),
axis.text.y = element_text(size=12, colour="black", family = "sans", angle = 0),
axis.text.x = element_text(size=12, colour="black", family = "sans", angle = 0, hjust = 0)
)+
theme(text = element_text(family = 'sans', size = 12),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
#,legend.position = 'none'
)+
scale_color_discrete(breaks = c(0, 1.0, 0.25))+
theme(legend.direction='vertical')+
labs(x=NULL,y=NULL) +
guides(fill=guide_colorbar(barheight = 18,title = "Variance explained (%)", title.position = "right"))+
coord_equal(ratio = 1.7)
ggsave(paste("results/dbRDA_HP_heat_n01_only_sex_age_new0318_3",".pdf", sep=""), p3, width=79 * 1.5, height=100 * 1.5, unit='mm')
#p3
排版Combo plots
组合多个子图为发表格式
library(cowplot)
p0 = plot_grid(p1, p2, p3, labels = c("A", "B", "C"), ncol = 3)
ggsave("results/dbRDA_plot02.pdf", p0, width=179 * 1.5, height=100 * 1.5, units = "mm")
使用此脚本,请引用下文:
Yong-Xin Liu, Lei Chen, Tengfei Ma, Xiaofang Li, Maosheng Zheng, Xin Zhou, Liang Chen, Xubo Qian, Jiao Xi, Hongye Lu, Huiluo Cao, Xiaoya Ma, Bian Bian, Pengfan Zhang, Jiqiu Wu, Ren-You Gan, Baolei Jia, Linyang Sun, Zhicheng Ju, Yunyun Gao, Tao Wen, Tong Chen. 2023. EasyAmplicon: An easy-to-use, open-source, reproducible, and community-based pipeline for amplicon data analysis in microbiome research. iMeta 2: e83. https://doi.org/10.1002/imt2.83
Copyright 2016-2024 Defeng Bai baidefeng@caas.cn, Chuang Ma 22720765@stu.ahau.edu.cn, Jiani Xun 15231572937@163.com, Yong-Xin Liu liuyongxin@caas.cn
猜你喜欢
iMeta高引文章 fastp 复杂热图 ggtree 绘图imageGP 网络iNAP
iMeta网页工具 代谢组MetOrigin 美吉云乳酸化预测DeepKla
iMeta综述 肠菌菌群 植物菌群 口腔菌群 蛋白质结构预测
10000+:菌群分析 宝宝与猫狗 梅毒狂想曲 提DNA发Nature
一文读懂:宏基因组 寄生虫益处 进化树 必备技能:提问 搜索 Endnote
16S功能预测 PICRUSt FAPROTAX Bugbase Tax4Fun
生物科普: 肠道细菌 人体上的生命 生命大跃进 细胞暗战 人体奥秘
写在后面
为鼓励读者交流快速解决科研困难,我们建立了“宏基因组”讨论群,己有国内外6000+ 科研人员加入。请添加主编微信meta-genomics带你入群,务必备注“姓名-单位-研究方向-职称/年级”。高级职称请注明身份,另有海内外微生物PI群供大佬合作交流。技术问题寻求帮助,首先阅读《如何优雅的提问》学习解决问题思路,仍未解决群内讨论,问题不私聊,帮助同行。
点击阅读原文