我们希望从一个文本文件中按行和列进行子集筛选,其中行号和列号从另一个文件中读取。需要排除表头(第一行)和行名(第一列)。
inputFile.txt 是一个制表符分隔的文本文件。
header 62 9 3 54 6 1
25 1 2 3 4 5 6
96 1 1 1 1 0 1
72 3 3 3 3 3 3
18 0 1 0 1 1 0
82 1 0 0 0 0 1
77 1 0 1 0 1 1
15 7 7 7 7 7 7
82 0 0 1 1 1 0
37 0 1 0 0 1 0
18 0 1 0 0 1 0
53 0 0 1 0 0 0
57 1 1 1 1 1 1
subsetCols.txt是一个没有空格的逗号分隔一行数字文件。在实际数据中,我们有500K列,并需要对其进行子集筛选,只保留约10K。
1,4,6
subsetRows.txt 是一个逗号分隔的一行数字文件,实际数据中有 20K 行,需要取其中约 ~300 行。
1,3,7
目前使用 cut 和 awk 循环的解决方案(相关帖子:使用 awk 选择行):
# define vars
fileInput=inputFile.txt
fileRows=subsetRows.txt
fileCols=subsetCols.txt
fileOutput=result.txt
# cut columns and awk rows
cut -f2- $fileInput | cut -f`cat $fileCols` | sed '1d' | awk -v s=`cat $fileRows` 'BEGIN{split(s, a, ","); for (i in a) b[a[i]]} NR in b' > $fileOutput
输出文件:result.txt
1 4 6
3 3 3
7 7 7
问题:
对于小文件,这个解决方案运行良好。但对于更大的文件,50K行和200K列,它需要太长时间,超过15分钟,仍在运行。我认为剪切列可以正常工作,选择行是较慢的部分。
有更好的方法吗?
实际输入文件信息:
# $fileInput:
# Rows = 20127
# Cols = 533633
# Size = 31 GB
# $fileCols: 12000 comma separated col numbers
# $fileRows: 300 comma separated row numbers
有关该文件的更多信息:文件包含GWAS基因型数据。每一行代表一个样本(个体),每一列代表一个SNP。为了进行进一步的区域分析,我们需要对样本(行)和SNP(列)进行子集处理,以使数据作为其他统计软件(如r)的输入更易于管理(减小)。
系统:
$ uname -a
Linux nYYY-XXXX ZZZ Tue Dec 18 17:22:54 CST 2012 x86_64 x86_64 x86_64 GNU/Linux
更新:以下解决方案由@JamesBrown提供,该方案导致我系统中的列顺序混乱,因为我使用的是不同版本的awk,我的版本是:GNU Awk 3.1.7