Python 将规范化从Pandas转换为AWK以提高性能
我有一个单细胞RNA测序数据集,我想对其进行规范化,但是由于它的大小(>1000000个细胞,~23000个基因),使用Python和Pandas根本不够高效(即使在优化数据类型、分区数据和128GB的RAM时) 因此,我希望在AWK(或其他有用的方法)中运行此规范化步骤,跳过内存密集型方法。从概念上讲,数据集是一个TSV文件,其中基因作为行,细胞作为列。大小约为130GB,在1GB的子集上进行测试时,需要6GB内存。在整个数据集上运行规范化是不可行的,但是规范化(比如说100个分区)仍然是一种非常无效的方法 这是一个规范化应该如何进行的示例(带有示例数据),我已成功地将其应用于较小的子集:Python 将规范化从Pandas转换为AWK以提高性能,python,pandas,awk,Python,Pandas,Awk,我有一个单细胞RNA测序数据集,我想对其进行规范化,但是由于它的大小(>1000000个细胞,~23000个基因),使用Python和Pandas根本不够高效(即使在优化数据类型、分区数据和128GB的RAM时) 因此,我希望在AWK(或其他有用的方法)中运行此规范化步骤,跳过内存密集型方法。从概念上讲,数据集是一个TSV文件,其中基因作为行,细胞作为列。大小约为130GB,在1GB的子集上进行测试时,需要6GB内存。在整个数据集上运行规范化是不可行的,但是规范化(比如说100个分区)仍然是一种
# determine dtypes and downcast to reduce memory usage
tmp_count_data = pd.read_csv(file_path, sep="\t", index_col=0, nrows=100)
tmp_float_cols = [c for c in tmp_count_data if tmp_count_data[c].dtype == "float64"]
tmp_float32_cols = {c: np.float32 for c in tmp_float_cols}
count_data = pd.read_csv(file_path, sep="\t", index_col=0, engine="c", dtype=tmp_float32_cols)
>>> count_data
c1 c2
-
GeneA 0.0 0.0
GeneB 1.0 0.0
GeneC 6.0 3.0
GeneD 4.0 3.0
def normalize(df):
# load dataframe values
dge = df.values
# calculate column sums
col_sums = np.apply_along_axis(sum,0,dge)
# divide cell value by column sum, multiply by 10000, add 1, apply natural logarithm
mat_dge_norm = np.log( dge/[float(x) for x in col_sums] * 10000 + 1 )
# add column and row names back to dataframe
df_dge_norm = pd.DataFrame(mat_dge_norm,index=df.index,columns=df.columns)
# return dataframe
return df_dge_norm
标准化应如下所示:
- 将C列中的单元格k除以C列的和
- 把这个除以10000
- 在此基础上添加1
- 取结果的自然对数
awk
执行此操作几乎很简单,不需要太多内存,但需要扫描文件两次
$ awk 'NR==FNR {c1+=$2; c2+=$3; next}
{print $1, log($2/(c1*1000)+1), log($3/(c2*1000)+1)}' file{,}
GeneA 0 0
GeneB 9.0905e-05 0
GeneC 0.000545306 0.000499875
GeneD 0.00036357 0.000499875
您也可以格式化数字,但不确定是否需要
如果时间安排不合理,您可以分割文件,计算块的总和,然后将它们相加,然后用总数分割块,同样,内存不是问题,而是可以并发运行的进程数,假设p个进程,您可以几乎成比例地减少时间 使用
awk
执行此操作几乎很简单,不需要太多内存,但需要扫描文件两次
$ awk 'NR==FNR {c1+=$2; c2+=$3; next}
{print $1, log($2/(c1*1000)+1), log($3/(c2*1000)+1)}' file{,}
GeneA 0 0
GeneB 9.0905e-05 0
GeneC 0.000545306 0.000499875
GeneD 0.00036357 0.000499875
您也可以格式化数字,但不确定是否需要
如果时间安排不合理,您可以分割文件,计算块的总和,然后将它们相加,然后用总数分割块,同样,内存不是问题,而是可以并发运行的进程数,假设p个进程,您可以几乎成比例地减少时间 如果是130GB,则可能是采用大数据方法(即Spark)的时候了,它应该可以跨多个节点处理此问题如果是130GB,则可能是采用大数据方法(即Spark)的时候了,它应该可以跨多个节点处理此问题