【问题标题】:Speed up nested for-loops加速嵌套的 for 循环
【发布时间】:2014-05-27 07:49:27
【问题描述】:

我正在尝试组合来自多个数据框的信息来填充一个大数据框。第一个数据框就像是对所有人类基因的概述:

gene_id chromosome  gene_start  gene_end
ENSG00000116396 1   110753965   110825722
ENSG00000228217 1   118320709   118321128
ENSG00000261716 1   149816065   149820591
ENSG00000223562 1   211355498   211356446
ENSG00000239859 1   36171626    36171875
ENSG00000197921 1   2460184     2461684
ENSG00000232237 1   201083081   201096312
ENSG00000212257 1   65488651    65488757
ENSG00000158887 1   161274525   161279762
ENSG00000238122 1   108803818   108816311
ENSG00000215846 1   159246293   159247282
ENSG00000266763 1   26238240    26238313
ENSG00000228634 1   32398621    32399576
ENSG00000177614 1   230457392   230561475
ENSG00000163462 1   155145873   155157447
ENSG00000204481 1   13668269    13673511

其次,我有许多文件(其中 516 个),包含如下数据:

Sample  Chromosome  Start   End Num_Probes  Segment_Mean
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   61735   82170           9       0.2560
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   82315   16869363        8678    -0.1199
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   16871278    17087292    85      -0.5386
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   17089349    17209603    23      -0.0807
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   17210652    17262232    57      0.2680
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   17262247    25583341    5240    -0.1228
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   25593128    25646986    28      -1.8216
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   25661501    30738534    2398    -0.0942
UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930 1   30739299    30745210    7       -1.3117

现在,我想创建某种循环,以获取第一个数据框中的每个基因。然后我想在检查基因位置的同时遍历所有 516 个数据帧。

所以对于每个基因和每个文件,我想将基因的开始和结束与每个样本片段的开始和结束进行比较,前提是它们在同一条染色体上。如果是这种情况,我想取段均值并将其放入一个新的大数据框中,其中gene_id 作为行名,文件名作为列名。

这是我已有的代码:

for(gene in 1:100){
  gene_id    <- genome[gene, 1]
  chromosome <- genome[gene, 2]
  gene_start <- genome[gene, 3]
  gene_end   <- genome[gene, 4]

  for(name in 1:length(dataframe_names)){
    df <- get(dataframe_names[name])
    for(segment in 1:nrow(df)){
      if(chromosome == as.character(df[segment,2])){
        if(gene_start > df[segment,3] && gene_start < df[segment,4] && gene_end > df[segment,3] && gene_end < df[segment,4]){
          data_matrix[gene,name] <- df[segment, 6]
        }
      }
    }
  }
}

此代码有效,但考虑到有 57 773 个基因,它确实很慢。 100 个基因的测试运行需要 1 小时,因此完整的运行可能需要 2-3 周...

我认为使用apply-family 会加快速度,但我以前从未使用过它们,所以我真的不知道该怎么做。网上的例子总是使用sum或mean之类的东西,但我不想这样的东西,我只是想比较数字。另外,我不知道apply-family 中的哪一个最适合我的需求。

你们想帮助我还是走上正轨?

【问题讨论】:

  • 这将有助于在您的示例中提供与基因重叠的 snp 片段,并澄清您是否期望每个基因不超过 1 个 snp 片段(这通过使用“gene_id”作为行来暗示。名称,因为 row.names 应该是唯一的)。
  • @Arun -- 我不明白您编辑 Sample 列的目的;看起来这些标识符是有意义的,并且只会通过使它们“漂亮”来引入错误。
  • @MartinMorgan,在此示例中,所有标识符都是相同的。因此,不确定它会在“此示例数据”中引入哪些错误。你能详细说明一下吗?
  • @Arun - 这似乎是一个毫无意义的编辑,丢失了对 OP 很重要的信息。如果身份很重要,并且都是相同的,那么合乎逻辑的做法就是完全删除它们!此外,如果您对这篇文章投了反对票,那么请重新考虑或至少证明这一点——OP 提供了一个可合理重现的示例和问题,即使乍一看标题看起来像是许多其他 StackOverflow 问题的重复。可能 cmets 部分不适合进行这些对话,非常抱歉。
  • @Arun,我知道这些标识符是相同的。这是构建这些文件的方式。这些文件不是我创建的,而是以这种格式下载的。

标签: r loops for-loop apply


【解决方案1】:

您需要做的第一件事就是停止重新发明轮子。熟悉生物导体包IRanges、GenomicRanges(和Biostrings 以确保完整性,尽管不是针对这个特定问题)。获得 GenomicRanges 后,请查看 findOverlaps 系列函数。

由于您的示例数据实际上没有任何重叠,因此我对其进行了修改

df1 <- structure(list(gene_id = structure(c(2L, 5L, 1L, 3L, 7L, 6L, 
   4L), .Label = c("ENSG00000207157", "ENSG00000223116", "ENSG00000229483", 
   "ENSG00000232849", "ENSG00000233440", "ENSG00000235205", "ENSG00000252952"
   ), class = "factor"), chromosome = c(13L, 13L, 13L, 13L, 13L, 
   13L, 13L), gene_start = c(23551994L, 23708313L, 23726725L, 23743974L, 
   23791571L, 23817659L, 93708910L), gene_end = c(23552136L, 23708703L, 
   23726825L, 23744736L, 23791673L, 23821323L, 93710179L)), .Names = c("gene_id", 
   "chromosome", "gene_start", "gene_end"), class = "data.frame", row.names = c(NA, 
   -7L))
 df2 <- structure(list(Sample = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
  1L, 1L), .Label = "UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930", class = "factor"), 
Chromosome = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Start = c(61735L, 
82315L, 16871278L, 17089349L, 17210652L, 17262247L, 25593128L, 
25661501L, 30739299L), End = c(82170L, 16869363L, 17087292L, 
17209603L, 17262232L, 25583341L, 25646986L, 30738534L, 30745210L
), Num_Probes = c(9L, 8678L, 85L, 23L, 57L, 5240L, 28L, 2398L, 
7L), Segment_Mean = c(0.256, -0.1199, -0.5386, -0.0807, 0.268, 
-0.1228, -1.8216, -0.0942, -1.3117)), .Names = c("Sample", 
"Chromosome", "Start", "End", "Num_Probes", "Segment_Mean"), class = "data.frame", row.names = c(NA, 
-9L))
df1$chromosome <- 1
df1[6,4] <- 30745215 # to show what happens when there are multiple overlaps

现在得到重叠

library(GenomicRanges)
Genes <- GRanges(df1$chromosome,
             IRanges(df1$gene_start, df1$gene_end), genes=df1$gene_id)

# make a list of the 512 others, and read 1 one for example
files <- list.files(pattern="csv") # assuming they are .csv files
snps0 <- read.csv(files[[1]])
snps  <- GRanges(snps0$Chromosome, IRanges(snps0$Start, snps0$End),
                 Segment_Mean=snps0$Segment_Mean)
olaps <- findOverlaps(query=snps, subject=Genes)

一旦有了重叠,您就可以将其用作合并原始数据框的基础

olaps2 <- as.data.frame(olaps)
df1$Row <- rownames(df1)
NewDF <- merge(df1,olaps2,by.x="Row",by.y="subjectHits",all=T,sort=F)
df2$Row <- rownames(df2)
NewDF2 <- merge(NewDF,df2,by.x="queryHits",by.y="Row",all.x=T,sort=F)[,c(-1,-2)] 
# drop the first 2 columns because they were just temporary for merging purposes
head(NewDF2,2)
      gene_id chromosome gene_start gene_end
1 ENSG00000223116          1   23551994 23552136
2 ENSG00000207157          1   23726725 23726825
                                                   Sample Chromosome    Start
1 UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930          1 17262247
2 UNDID_p_TCGA_353_354_355_37_NSP_GenomeWideSNP_6_H10_1376930          1 17262247
   End Num_Probes Segment_Mean
1 25583341       5240      -0.1228
2 25583341       5240      -0.1228

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    相关资源
    最近更新 更多