前段时间,我们曾经推出过关于免疫浸润的教程,用的是CIBERSORT软件。代码是我之前就测试过的,几百个样本大概不到十分钟就能够运行完成,非常顺利,代码也很简单。
可是,前几天有粉丝说在用CIBERSORT的进行免疫微环境分析的时候,程序总是一直在运行。等了好几个小时也没有运行完成,耐心的他,最长等了整整两天的时间。一开始我也没有多想,第一反应,以为是跑的数据太大了,电脑的配置不够好,导致运行时间过长。所以建议粉丝换一台电脑,或者用小一点的测试数据进行测试。结果他反馈说用了仅仅两个样本去跑代码,CIBERSORT依然要等待很长的时间。我一想事情不对,这肯定是有问题了,此时没那么简单。
常规来说,几百个样本都能够在短短数分钟内或者十几分钟内运行完毕。既然已经换了电脑,换了数据,依然要花费很长的时间不能运行成功。那么最有可能怀疑的就是代码的问题了。
下面是我解决这个问题的整个历程。首先,我看了一下发给大家的学习资料。在CIBERSORT所用的代码中,有一个CIBERSORT()函数里面有个permutation的参数,这个参数表示设置的越大运行的时间越长,于是乎为了找出问题症结的所在,首先要排除一切可能的因素,把问题简单化。于是,我把这个参数设置为10(当然常规一般要设置为500或者1000)。在我自己的电脑上找了10个样本去进行测试,发现结果跟粉丝的反应是一样的,等待了5分钟以后没有任何反应。结果如图所示:
首先想了一下,程序是不是被挂起了,没有真正执行呢?看了下任务管理器:
内存占用363.7MB,肯定是在飞速运算没错了。但是磁盘IO是0,完全没有读写,不应该啊。心想,万一程序在计算当中,只是任务管理器一时间没有发现呢?于是去硬盘目录下查找有没有文件在悄悄生成,或者文件大小悄悄更改。结果,并没有。在硬盘中也没有生成任何类型的新文件。
那么问题又回来了,再次确定就是代码的问题了,肯定代码卡在了哪一步。难道是官方提供的CIBERSORT.R这个代码?虽然带有怀疑,但是毕竟是发表过文章的代码,依旧不敢百分百确定。带着怀疑的态度,打开了这个官方提供的代码。一行一行往下撸代码,因为上层代码是卡在CIBERSORT()函数这里,所以首先看的也是这个函数。我们可以大致看一眼这个代码的截图,还是很工整的,说明原作者有着很好的代码书写习惯和技巧。
Debug怎么做?最笨的办法就是一行一行试运行。我先给函数的几个必要的参数赋了值,然后一行一行往下运行,直到下面这一行的时候,看到一个非常奇怪的while循环。
这什么鬼!?Sys.Date()是为了调用系统时间,那么这句话的含义是什么呢?看了一下数值,这句话的意思是提取当前的月份,如果月份大于5,则运行下一个循环。运行结果如下:
虽然不明白原作者是啥意思,不过这句话和计算完全不搭噶啊好不好。首先说,这句话写的就有毛病,字符串”06”怎么能和数字5比较呢,最起码用as.numeric()转换下对象类型吧。好,就算抛开这点暂且不说,现在是6月份,的确是大于5的,然后程序就会跳过下面的运算,直接进入next下一个,作者的用意是什么,实在搞不懂。
发现问题了,不代表问题解决了。我们继续往下看,下面出现了一个while循环:
这段很好理解,在所有的N个样本中,逐个计算免疫细胞的比例,每次计算完成一个,计数器itor增加1,直到计数器大于样本数量为止。按道理来说,这个循环没有问题,而且很好理解,不过还是有改进空间,话说为啥不用apply,高级迭代循环不香吗?试问,如果有几百个样本,apply的运行速度要远远超过普通的while和for循环。好吧,这些都不重要,暂且忍耐心中的想法,继续往下看,找到bug才是最关键的。一行一行撸下去的时候,再次发现一个很神奇的东西:
这句话啥意思?提取年份和2019比较,看一下运行结果:
完蛋了!现在是2020年,所以条件判断始终是TRUE,换句话说,只要while循环运行到这里,都会判断为true,然后就执行next,而计数器itor的自增被作者写在循环的最后一行,始终未变!换句话说,在外层的while循环中,一直条件判断都是真!说通俗一点,进入了死循环。说的难听点,这个代码因为一个bug,变成了一个病毒,除了会占用CPU和内存,不管再等上多久,都不会有结果。
既然找到问题所在,那就简单了,删除这两段无用的系统时间判断语句,再次运行。Bingo!妥妥地解决问题,几分钟快速计算完成。到此,我们的问题就算定位,并且解决啦。
不过,为了进一步优化,我在循环中加了一个进度提醒,免得再出什么幺蛾子。
运行结果如下,当然有兴趣的同学可以用tk加一个GUI的进度条。
好了,此次debug顺利完成,解决了一个算是比较重要的问题。
结语
在我们的数据分析。和运行代码的过程当中,会遇到各种各样的报错。遇到报错的时候,应该有完整的清晰的debug思路。就我个人的经验而言,首先第一是排除数据或者数据格式的问题。第二是排除硬件本身的问题,比如说软件有一些包没有装好,或者某些环境没有配置好。第三就去找代码本身的问题,在代码debug的过程当中有很多的技巧,在这里就不一一细说了。总之,我们一定要有耐心去找到问题的症结所在。
判断一个人能力的高低,不在于他能否进行某一项分析,或者能否运行某一些代码,只要不笨,稍微学点R语言基础,有现成的代码,谁都会运行。生信分析师技能的高下,在于自身解决问题的能力。
之前跑过,就是这样一直跑,最后换个了个R包才成功
请问是换了个什么包呢