生信脚本计算资源使用指南
作为生物信息学从业人员,经常需要自行开发脚本进行数据格式整理和格式转换。因此,虽然Python
和R
中自带的包可以很轻松的实现绝大多数功能,但是其在处理大型数据(指超过1G以上的数据)时,其效率实在不敢恭维。
虽然可以通过给这些程序分配更多的内存来解决这一问题,但是在实际生产或数据荟萃分析时,无限上调内存显然是不现实的。因此需要生信脚本编写者更好的对计算资源(本文只涉及内存、CPU)加以更合理的使用。
下面将会简单介绍在Python
和 R
中减少内存消耗上限的小技巧,供大家参考。
1. Python
目前 Python 作为数据挖掘领域最为主流的语言之一,其内设的扩展包(pandas
、numpy
、scipy
等)基本上解决了绝大多数基础操作的需要。但是过于方便的使用,就造成了这些包,在处理小数据时简洁优雅,但是处理数据量较大的数据时,就相对苦手了,尤其是pandas
。下面是几个针对pandas
的小建议:
1.1 Pandas 数据框瘦身方案
改变数据基本数据类型,可以对内存占用提供较大的优化空间。数据类型名称前面的数字是指存储值所需的内存位数。
例如:
- int8使用8位或 1 字节
- int16使用 16 位或 2 个字节。
范围越大,它消耗的内存就越多。这意味着int16使用两倍的内存,int8而int64使用八倍的内存int8。uint8等uint16 是指无符号整数,而 int指的是有符号整数。分配的内存量没有区别,但顾名思义,无符号整数只能存储正值,即 0-255,对于uint8。 这同样适用于uint16,uint32和uint64。
对于pandas.read_csv()
,在默认情况下,会直接使用int64 和 float64 作为默认的整型和浮点型变量的类型,其实对于很多数据而言,这种类型指定纯属杀鸡用牛刀了,比如对于基因组坐标,int16 也就差不多够用。对于bed
、gff
或者vcf
文件来说,通过类型的转化,可以节约的内存是相当客观的。
1.2 对于读入大数据框的优化
对于生信操作而言,表格之间的相互关联也是常规操作。但是很多情况下,我们需要读一个非常大的数据集,来和小的数据集进行关联(常见于注释)。这种情况下,将整个数据库都扔进内存,显然不是最好的实现注释过程的方式。
对于这种情况,通过采用SQLite
以磁盘空间换取内存相对更小的占用,其实才是更为合理的实现方式。
import sqlite3
from sqlalchemy import create_engine
csv_database = create_engine('sqlite:///csv_database.db')
chunk_size=50000
batch_no=1
for chunk in pd.read_csv('yellow_tripdata_2016-02.csv',chunksize=chunk_size,iterator=True):
chunk.to_sql('chunk_sql',csv_database, if_exists='append')
batch_no+=1
print('index: {}'.format(batch_no))
### this example is from https://towardsdatascience.com/loading-large-datasets-in-pandas-11bdddd36f7b
1.3 大数据框排序
排序问题基本上算是在算法领域最基础的问题了,但是在Python的pandas 中提供的sort 函数,给出的方案其实不是特别适合大量数据,因为其实现的基本原理是将数据全部读到内存中,然后再进行排序。当你需要把一个几十G的文件load到内存中的时候,这种就实在不是一个合理的解决方式。
除了上述利用数据库工具解决之外,也可以通过Linux shell中自带的split
+ sort
工具实现分步排序法。例如:
split -l 1000 data.csv data
sort -nrk3 data.csv
sort -m sorted_data_* > final_sorted_data.csv
2. R
对于R 本人没有其他特殊建议,但是很多时候R中涉及的最多的是构造一个数据结构,但是数据结构需要通过数据框或者其他类型的数据进行转化。
此时,用于构建数据对象的变量其实可以释放。R解析器不会自动的为你做上述操作,需要通过R中的rm函数进行释放。
library(Seurat)
expr_data = read.csv("data.csv")
seurat_obj = Create_10XChrome(expr_data)
#####
rm(list = "expr_data") ### 删除过渡数据expr_data
3. 小结
上述是一些生信常用工具中节省内存的方式,其实从功能上来说,绝大多数的扩展包内的自带函数是可以解决问题的,但是性能上的优劣,主要还是看各位程序编写者的细心程度,希望大家能在自己编写脚本的过程中,合理利用计算资源。更高效的实现分析目的。 :)