Robust火山图:一种含离群值的代谢组数据差异分析方法

代谢组学中差异代谢物的识别仍然是一个巨大的挑战,并在代谢组学数据分析中发挥着突出的作用。由于分析、实验和生物的模糊性,代谢组学数据集经常包含异常值,但目前可用的差异代谢物识别技术对异常值很敏感。作者这里提出了一种基于权重的具有稳健性火山图方法,助于从含有离群值的代谢组数据中更加准确鉴定差异代谢物。

image

作者将提出的方法与其它9种代谢组中常用的方法(包含t-test)进行比较,发现有较低的misclassification error rates(MERs)和较高的AUC,证明了该方法的优越性。

MERs比较
AUC比较

安装加载数据集

Github:https://github.com/nishithkumarpaul/Rvolcano

library(devtools)
install_github("nishithkumarpaul/Rvolcano")
library(Rvolcano)
data("DummyFullData")

dim(DummyFullData)
[1] 40 40

数据集由40行代谢物和40个样本组成,其中(癌症和健康组各20生物学重复)

image

计算foldchange

fcval <- foldChngCalc(DummyFullData,nSampG1 = 20,nSampG2 = 20)
head(fcval)

## 查看该函数
edit(foldChngCalc)

function (data, nSampG1, nSampG2) 
{
  g1fold <- apply((data[, 1:nSampG1]), 1, weightedMean)
  g2fold <- apply((data[, (nSampG1 + 1):(nSampG1 + nSampG2)]), 
    1, weightedMean)
  foldChange <- g2fold - g1fold
  return(foldChange)
}

我们查看下foldChngCalc该函数,可以看到主要是通过apply函数计算了weightedMean值,即加权平均数, 而不是我们常用的mean(算术平均数)。

算术平均数又称均值,是统计学中基本的平均指标,就是简单的把所有数加起来然后除以个数。

加权平均数即加权平均值,是将各数值乘以相应的权数,然后加总求和得到总体值,再除以总的单位数。

通过一个例子计算下,观察weightedMean函数和mean有啥区别,,我们创建一个正态分布的向量集x和一个含有较高离群值的向量集,分布计算一下结果。

> set.seed(123)
> x<-c(rnorm(200,3,1)) 
> x1<-c(rnorm(180,3,1),rnorm(20,60,3)) #contain 20 outliers#
> weightedMean(x)
[1] 2.957601
> mean(x)
[1] 2.99143
> weightedMean(x1)
[1] 3.062994
> mean(x1)
[1] 8.712792

## 查看该函数的计算方法
function (a, b = 0.2) 
{
  w <- NULL
  pw <- NULL
  for (i in 1:length(a)) {
    w[i] <- exp(-(b/2) * (mad(a)^-2) * (a[i] - median(a))^2)
    pw[i] <- w[i] * a[i]
  }
  tpw <- sum(pw)
  tw <- sum(w)
  wm <- tpw/tw
  dd <- c(tpw, tw, wm)
  return(wm)
}

结果发现,不含离群值时,加权与算术平均数都一样,而含有离群值时候,结果容易形成误差,算术平均数易受极端数据的影响,极端值的出现,会使平均数的真实性受到干扰,加权差异有助于在进行计算时考虑更多数据,以便获得最准确的结果。

计算Pvalue

使用p.valcalc函数进行差异分析,使用robust vesion的t-test获取p值,公式可以查看函数源码,用到了weightedVar加权方差

## 添加Pvalue
pval <- NULL
for (i in 1:dim(DummyFullData)[1]){
  pval[i] <- p.valcalc(DummyFullData[i,1:20],DummyFullData[i,21:40])
  }
  
  ##查看该源码
  edit(p.valcalc)
  function (x, y) 
{
  t.stat <- (weightedMean(x) - weightedMean(y))/sqrt(((length(x) - 
    1) * weightedVar(x) + (length(y) - 1) * weightedVar(y)) * 
    (1/(length(x) + length(y) - 2)) * ((1/length(x)) + 1/length(y)))
  pval <- 2 * pt(abs(t.stat), (length(x) + length(y) - 2), 
    lower.tail = FALSE)
  return(pval)
}

绘制火山图

log2foldchange和Pvalue都有了,直接使用RobVolPlot函数绘图

##Robust volcano plot
RobVolPlot(fcval,pval,cexcutoff = 0.7,cexlab = 0.8,
           main = 'Volcano Plot',
           xlab = 'log2fc',
           ylab = '-log(Pvalue)',
           plimit = 0.05,fclimit = 2)
edit(RobVolPlot)
image

ggplot2绘图

已经得到了log2foldchange和Pvalue数据了,我们就可以自己拿着数据绘制图形了

library(ggrepel)
## 获取数据
result <- data.frame(log2foldchange = fcval,p_value = pval)
result$threshold = factor(ifelse(result$p_value < 0.05 & abs(result$log2foldchange) >= 1, 
                                 ifelse(result$log2foldchange>= 1 ,'Up','Down'),'NoSignificance'),
                                 levels=c('Up','Down','NoSignificance'))
##差异代谢物
re <- subset(result,p_value < 0.05)
ggplot(result,aes(log2foldchange, -log10(p_value)))+
  geom_point(aes(color = threshold), size = 5) +
  scale_colour_manual(values = c('#fb81f5', '#6868ed', 'gray40'), labels = c('Enriched metabolites', 'Depleted metabolites', 'No diff')) +
  # 添加x轴标签
  xlab(bquote(Log[2] ~ '(fold change)')) +
  # 添加y轴标签
  ylab(bquote(-Log[10] ~ italic('Pvalue')))+
  # 添加标签:
  geom_text_repel(data = re, aes(color = threshold,label = rownames(re)),max.overlaps = 20,
                  size = 4.8 ,fontface = "bold",arrow = arrow(length=unit(0.01, "npc")),force = 1, max.iter = 3e3,
                  box.padding = unit(0.6, 'lines'), segment.color = 'black', show.legend = FALSE)+
  theme_bw()+
  # 调整主题和图例位置:
  theme(panel.grid = element_blank(),
        legend.position = c(0.01,0.25),
        legend.justification = c(0,1)
  )+
 geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "grey",size = 1)+
 geom_vline(xintercept = c(-1.2,1.2), linetype = "dashed", color = "grey",size = 1)


image

参考资料

  1. https://bmcbioinformatics.biomedcentral.com/articles/10.1186/s12859-018-2117-2

  2. 如何计算加权方差:https://cn.ebrdbusinesslens.com/88-how-8599659-calculate-weighted-variancel-37590

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,230评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,261评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,089评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,542评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,542评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,544评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,922评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,578评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,816评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,576评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,658评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,359评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,920评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,859评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,381评论 2 342

推荐阅读更多精彩内容