【问题标题】:R: Avoiding loops when using multiple conditions that are dependent on each otherR:使用多个相互依赖的条件时避免循环
【发布时间】:2017-09-11 22:34:41
【问题描述】:

不确定我的标题是否像我希望的那样清晰。下面是一些使用循环写出的代码:

for(i in 1:length(variantTable[,1])){
  #N stores counts of numbers of population totals of populations that contain the variant in question
  N = 0
  #NF.pop stores frequencies
  NF.EAS = 0
  NF.AMR = 0
  NF.EUR = 0
  NF.SAS = 0
  if(variantTable[i,]$EAS_MAF > 0){
    NF.EAS = EAScount * variantTable[i,]$EAS_MAF
    N = N + EAScount
  }
  if(variantTable[i,]$AMR_MAF > 0){
    NF.AMR = AMRcount * variantTable[i,]$AMR_MAF
    N = N + AMRcount
  }
  if(variantTable[i,]$EUR_MAF > 0){
    NF.EUR = EURcount * variantTable[i,]$EUR_MAF
    N = N + EURcount
  }
  if(variantTable[i,]$SAS_MAF > 0){
    NF.SAS = SAScount * variantTable[i,]$SAS_MAF
    N = N + SAScount
  }
  variantTable[i,]$nonAFR_N <- N

  variantTable[i,]$nonAFR_weighted <- (NF.EAS + NF.AMR + NF.EUR + NF.SAS)/N
}

如您所见,variantTable[i,]$nonAFR_weighted 是根据跨多个列(EAS_MAF、AMR_MAF、AFR_MAF、EUR_MAF、SAS_MAF)的条件计算得出的。

我知道循环并不是在 R 中执行此类操作的最快方法,尤其是考虑到我的数据集包含 900000 行这一事实。

我刚刚开始使用 ifelse 和 apply 方法,但不确定如何在这种情况下使用它们。我确实尝试创建一个函数,它只接收一行并计算该行的值,然后使用 apply 方法,但这并没有奏效,因为我不确定输入应该是什么。

关于如何最好地处理此类问题的任何建议?

编辑:这是我的数据的输入:

> dput(head(variantTable))
structure(list(CHROM = c("1", "1", "1", "1", "1", "1"), POS = c(69224L, 
69428L, 69486L, 69487L, 69496L, 69521L), ID = c("rs568964432", 
"rs140739101", "rs548369610", "rs568226429", "rs150690004", "rs553724620"
), REF = c("A", "T", "C", "G", "G", "T"), ALT = c("T", "G", "T", 
"A", "A", "A"), AF = c(0.000399361, 0.0189696, 0.000199681, 0.000399361, 
0.000998403, 0.000399361), AC = c(2L, 95L, 1L, 2L, 5L, 2L), AN = c(5008L, 
5008L, 5008L, 5008L, 5008L, 5008L), EAS_AF = c(0, 0.003, 0.001, 
0, 0, 0), AMR_AF = c(0.0029, 0.036, 0, 0, 0.0014, 0.0029), AFR_AF = c(0, 
0.0015, 0, 0.0015, 0.003, 0), EUR_AF = c(0, 0.0497, 0, 0, 0, 
0), SAS_AF = c(0, 0.0153, 0, 0, 0, 0), consequence = c("nonsynonymous SNV", 
"nonsynonymous SNV", "synonymous SNV", "nonsynonymous SNV", "nonsynonymous SNV", 
"nonsynonymous SNV"), gene = c("OR4F5", "OR4F5", "OR4F5", "OR4F5", 
"OR4F5", "OR4F5"), refGene_id = c("NM_001005484", "NM_001005484", 
"NM_001005484", "NM_001005484", "NM_001005484", "NM_001005484"
), AA_change = c("('D', 'V')", "('F', 'C')", "('N', 'N')", "('A', 'T')", 
"('G', 'S')", "('I', 'N')"), X0.fold_count = c(572L, 572L, 572L, 
572L, 572L, 572L), X4.fold_count = c(141L, 141L, 141L, 141L, 
141L, 141L), EAS_MAF = c(0, 0.003, 0.001, 0, 0, 0), AMR_MAF = c(0.0029, 
0.036, 0, 0, 0.0014, 0.0029), AFR_MAF = c(0, 0.0015, 0, 0.0015, 
0.003, 0), EUR_MAF = c(0, 0.0497, 0, 0, 0, 0), SAS_MAF = c(0, 
0.0153, 0, 0, 0, 0), nonAFR_AF = c(0.0029, 0.104, 0.001, 0, 0.0014, 
0.0029), nonAFR_N = c(309227, 1128036, 262551, 0, 309227, 309227
), nonAFR_weighted = c(0.0029, 0.0261704282487438, 0.001, NaN, 
0.0014, 0.0029)), .Names = c("CHROM", "POS", "ID", "REF", "ALT", 
"AF", "AC", "AN", "EAS_AF", "AMR_AF", "AFR_AF", "EUR_AF", "SAS_AF", 
"consequence", "gene", "refGene_id", "AA_change", "X0.fold_count", 
"X4.fold_count", "EAS_MAF", "AMR_MAF", "AFR_MAF", "EUR_MAF", 
"SAS_MAF", "nonAFR_AF", "nonAFR_N", "nonAFR_weighted"), row.names = c(NA, 
6L), class = "data.frame")

人口计数(EAScount、AMRcount 等)之前已定义如下:

EAScount <- length(variantTable$EAS_MAF[variantTable$EAS_MAF>0])
AMRcount <- length(variantTable$EAS_MAF[variantTable$AMR_MAF>0])
AFRcount <- length(variantTable$EAS_MAF[variantTable$AFR_MAF>0])
EURcount <- length(variantTable$EAS_MAF[variantTable$EUR_MAF>0])
SAScount <- length(variantTable$EAS_MAF[variantTable$SAS_MAF>0])

我正在寻找的输出是variantTable$nonAFR_n 和variantTable$nonAFR_weighted 的计算。下面是一个正确计算的例子:

> variantTable[2,]
  CHROM   POS          ID REF ALT        AF AC   AN EAS_AF AMR_AF AFR_AF EUR_AF SAS_AF       consequence
2     1 69428 rs140739101   T   G 0.0189696 95 5008  0.003  0.036 0.0015 0.0497 0.0153 nonsynonymous SNV
   gene   refGene_id  AA_change X0.fold_count X4.fold_count EAS_MAF AMR_MAF AFR_MAF EUR_MAF SAS_MAF
2 OR4F5 NM_001005484 ('F', 'C')           572           141   0.003   0.036  0.0015  0.0497  0.0153
  nonAFR_AF nonAFR_N nonAFR_weighted
2     0.104  1128036      0.02617043

【问题讨论】:

  • 你可以使用 apply 来做这个(我不确定你是否需要 ifelse,因为 else 什么都不做)。您能否提供一个可重现的数据示例?你可以dput(head(variantTable)) 并发布结果
  • 嗨,我已经编辑了我的帖子以包含 dput。谢谢。
  • 不用担心。另外,EAScount、AMRcount、EURcount 和 SAScount 是否在循环和常量之前定义?
  • 请提供您希望结果看起来如何的示例。如果我们也能看到,提供解决方案可能会更快,即使您只计算第一行。
  • 我添加了有关 EAScount 等的详细信息,以及结果应该是什么样子的示例。谢谢。

标签: r loops apply


【解决方案1】:

这行得通吗?

library(dplyr)
variantTable %>% mutate(
  NF.EAS = EAScount * EAS_MAF,
  NF.AMR = AMRcount * AMR_MAF,
  NF.EUR = EURcount * EUR_MAF,
  NF.SAS = SAScount * SAS_MAF,
  nonAFR_N = EAScount * (EAS_MAF>0) + AMRcount * (AMR_MAF>0) + EURcount * (EUR_MAF>0) + SAScount * (SAS_MAF>0),
  nonAFR_weighted = (NF.EAS + NF.AMR + NF.EUR + NF.SAS)/nonAFR_N) %>%
  select(-c(NF.EAS,NF.AMR,NF.EUR,NF.SAS))

mutate 向表中添加或修改列,它允许使用不带$ 表示法的列名。您的if 结构不是必需的,因为乘以零无论如何都会得到默认的零值,因此可以简化脚本的第一部分。

当与算术运算符一起使用时,布尔值被强制转换为整数 01,因此我也不需要所有 if 结构来计算 N

最后一栏非常简单。

所有这些操作都是矢量化的,这意味着我直接加、减、乘、除列而不是离散值,这对机器来说更快,更容易看。

而且,更高效且更易于阅读:

EAScount <- sum(variantTable$EAS_MAF>0)
AMRcount <- sum(variantTable$AMR_MAF>0)
AFRcount <- sum(variantTable$AFR_MAF>0)
EURcount <- sum(variantTable$EUR_MAF>0)
SAScount <- sum(variantTable$SAS_MAF>0)

【讨论】:

  • 谢谢,这非常有效并且非常迅速。我不完全确定你的答案是怎么回事?特别是 %>%?
  • 它被称为管道操作符,尝试找到dplyr 的教程并阅读网站上的几个问题,如果您打算继续使用 R,这将是一个很好的时间,我会编辑我的答案以澄清一下
  • 感谢您的详细解释。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
  • 2018-09-03
  • 2021-11-30
  • 2012-02-15
  • 1970-01-01
相关资源
最近更新 更多