美文网首页
列表转数据框-我的计算机还能救一救

列表转数据框-我的计算机还能救一救

作者: Stone_Stan4d | 来源:发表于2018-12-08 18:04 被阅读32次

    我曾经有一个表,它叫lncmiRcode,它这么大:

    > dim(lncmiRcode)
    [1] 208303      3
    

    你没看错,它只有3列,但是有20.8万行
    它来自于另一个更大的表miRcode, 128.6w行 * 12列:

    # 只保留lncRNA
    tmpIndex = miRcode$gene_class %in% 
      c('lncRNA, intergenic', 'lncRNA, overlapping', 'pseudogene')
    lncmiRcode = miRcode[tmpIndex,c(2, 3, 4)]
    lncmiRcode = dplyr::distinct(lncmiRcode)#去除重复的行
    
    image.png
    这些都不重要,重要的是,它的第三列是不规范的,用一个/就把两个不同的miRNA给打发了,是几个意思呢?
    image.png
    我要把这些miRNA分离出来,让它们各自占用一行,像这样:
     gene_symbol gene_class    microrna
    1        MYH16 pseudogene       miR-7
    2        MYH16 pseudogene     miR-7ab
    3        MYH16 pseudogene  miR-133abc
    4        MYH16 pseudogene      miR-96
    5        MYH16 pseudogene     miR-507
    6        MYH16 pseudogene    miR-1271
    7        MYH16 pseudogene   miR-135ab
    8        MYH16 pseudogene miR-135a-5p
    9        MYH16 pseudogene     miR-138
    10       MYH16 pseudogene   miR-138ab
    

    其实这些小分子(miRNA)的前缀是不一样的,有let,有/miR

    tmp = substr(lncmiRcode$microrna, 1, 3) 
    > table(tmp)
    tmp
       let    miR 
      1952 206351 
    

    把冰箱装进大象一共有几步呢?


    先打开冰箱,分开绑到一起的miRNAs:

      tmpmiR= strsplit(lncmiRcode$microrna, split = '/') 
    #用'/'绑到一起,就用'/'分开
      for(i in 1:length(tmpmiR)){
        miRs = tmpmiR[i][[1]]
        if(length(miRs) > 1){
        # 如果有绑到一起的情况,就执行{}内代码,改变tmpmiR[[i]]的内容
          miRs[2:length(miRs)] = paste(tmp[i], miRs[2:length(miRs)],  sep = '-')
        #加上存在tmp里的前缀,当然用i来一一对应
          tmpmiR[i][[1]] = miRs}
        }
    
    tmpmiR lncmiRcode

    是不是一一对应?


    接下来把大象塞进冰箱,让分开的miRNA去于lncRNA配对,且形成数据框:

    #先构造一个函数,实现把绑一起的miRNA合成一组,
    #因为它们靶向相同的lncRNA,然后组成数据框
      tmpfun = function(i){
        tmpRow = data.frame(gene_symbol = unlist(rep(lncmiRcode[i, 1], length(tmpmiR[[i]]))),
                            gene_class = unlist(rep(lncmiRcode[i, 2], length(tmpmiR[[i]]))),
                            microrna = tmpmiR[[i]])
        return(tmpRow)
        }
    
    #再用神奇的lapply,对'lncmiRcode'中的每一个元素,实行该函数,#这样就把大象装进冰箱啦!
      tmpMat = lapply(1:length(tmpmiR), tmpfun)
    

    如果事情到此就结束了,我还有必要写一个笔记记下来吗?问题在哪里?

    返回的tmpMat,是一个list,而不是data.frame:

    > tmpMat[1:3]
    [[1]]
      gene_symbol gene_class microrna
    1       MYH16 pseudogene    miR-7
    2       MYH16 pseudogene  miR-7ab
    
    [[2]]
                gene_symbol gene_class   microrna
    gene_symbol       MYH16 pseudogene miR-133abc
    
    [[3]]
      gene_symbol gene_class microrna
    1       MYH16 pseudogene   miR-96
    2       MYH16 pseudogene  miR-507
    3       MYH16 pseudogene miR-1271
    

    昨天,我用了一个for循环,这么长的list,循环了有15~20min吧,显然我是不愿意的:

      for(i in 1:length(tmpMat)){
        tmpMat0 = rbind(tmpMat0, tmpMat[[i]])
      }
      
      lncmiRcode = lncmiRcode[!grepl('/', lncmiRcode$microrna),]
      lncmiRcode = rbind(lncmiRcode, tmpMat0)
      save(lncmiRcode, file = 'lncRNA-miR-miRcode.rdata')
    

    第三步,关上冰箱,把藏在list里的data.frame整理出来:
    搜索如此:

    image.png
    第四条解释
    image.png
    image.png
    image.png
    image.png

    看得出来,data.table::rbind.list()函数是最快的。我自己尝试一下看看:

    data = tmpMat[1:5000]
    
    
    library(rbenchmark)
    benchmark(do.call(rbind, data), ldply(data, rbind), rbind.fill(data), 
              rbind_all(data), rbindlist(data))
    > benchmark(do.call(rbind, data), ldply(data, rbind), rbind.fill(data), 
    +           rbind_all(data), rbindlist(data))
                      test replications elapsed relative user.self sys.self user.child
    1 do.call(rbind, data)          100    4.30   71.667      4.27     0.00         NA
    2   ldply(data, rbind)          100   12.08  201.333     11.97     0.00         NA
    3     rbind.fill(data)          100    6.50  108.333      5.97     0.03         NA
    4      rbind_all(data)          100    0.31    5.167      0.30     0.00         NA
    5      rbindlist(data)          100    0.06    1.000      0.06     0.00         NA
      sys.child
    1        NA
    2        NA
    3        NA
    4        NA
    5        NA
    There were 50 or more warnings (use warnings() to see the first 50)
    

    我选择用这个data.table::rbindlist,运行很快,一秒不到:

    tmpMat0 = data.table::rbindlist(tmpMat)
    > head(tmpMat0)
       gene_symbol gene_class   microrna
    1:       MYH16 pseudogene      miR-7
    2:       MYH16 pseudogene    miR-7ab
    3:       MYH16 pseudogene miR-133abc
    4:       MYH16 pseudogene     miR-96
    5:       MYH16 pseudogene    miR-507
    6:       MYH16 pseudogene   miR-1271
    

    关于benchmark:
    Benchmark Experiments

    相关文章

      网友评论

          本文标题:列表转数据框-我的计算机还能救一救

          本文链接:https://www.haomeiwen.com/subject/daiqhqtx.html