我有一个目录ballgown
,其中有大约 1000 个子目录作为示例名称。每个子目录都有一个文件t_data.ctab
。所有子目录中的文件名都相同。
ballgown
|_______TCGA-A2-A0T3-01A
|___________ t_data.ctab
|_______TCGA-A7-A4SA-01A
|___________ t_data.ctab
|_______TCGA-A7-A6VW-01A
|___________ t_data.ctab
像上面ballgown
有1000个子目录。所有这 1000 个子目录中的文件t_data.ctab
如下所示,其中包含各列:
t_id chr strand start end t_name num_exons length gene_id gene_name cov FPKM
1 1 - 10060 10614 MSTRG.1.1 1 555 MSTRG.1 . 0.000000 0.000000
2 1 + 11140 30023 MSTRG.10.1 12 3981 MSTRG.10 . 2.052715 0.284182
3 1 - 11694 29342 MSTRG.11.1 8 6356 MSTRG.11 . 0.557588 0.077194
4 1 + 11869 14409 ENST00000456328.2 3 1657 MSTRG.10 DDX11L1 0.000000 0.000000
5 1 + 11937 29347 MSTRG.10.3 12 3544 MSTRG.10 . 0.000000 0.000000
6 1 - 11959 30203 MSTRG.11.2 11 4547 MSTRG.11 . 0.369929 0.051214
7 1 + 12010 13670 ENST00000450305.2 6 632 MSTRG.10 DDX11L1 0.000000 0.000000
8 1 + 12108 26994 MSTRG.10.5 10 5569 MSTRG.10 . 0.057091 0.007904
9 1 + 12804 199997 MSTRG.10.6 12 3567 MSTRG.10 . 0.000000 0.000000
10 1 + 13010 31097 MSTRG.10.7 12 4375 MSTRG.10 . 0.000000 0.000000
11 1 - 13068 26832 MSTRG.11.3 9 5457 MSTRG.11 . 0.995280 0.137788
t_data.ctab
我只想从所有文件中提取t_name
并列FPKM
并创建一个新文件。在新文件中,该FPKM
列应该是样本名称。它应该如下所示:
t_name TCGA-A2-A0T3-01A TCGA-A7-A4SA-01A TCGA-A7-A6VW-01A
MSTRG.1.1 0 0.028181 0
MSTRG.10.1 0.284182 0.002072 0.046302
MSTRG.11.1 0.077194 0.685535 0.105849
ENST00000456328.2 0 0.307315 0.038961
MSTRG.10.3 0 0.446015 0.009946
MSTRG.11.2 0.051214 0.053577 0.036081
ENST00000450305.2 0 0.110438 0.040319
MSTRG.10.5 0.007904 0 1.430825
MSTRG.10.6 0 0 0.221105
MSTRG.10.7 0 0.199354 0
MSTRG.11.3 0.137788 0.004792 0
如果是两个或三个文件,我可以cut
在每个文件上使用 -f6,12 然后加入它们。但我现在有大约 1000 个文件。
答案1
尝试这个简单的方法:
首先做:
awk 'FNR==1 { print substr(FILENAME,1,16) >substr(FILENAME,1,16)".tmp" }
FNR >1 { print $12 > substr(FILENAME,1,16)".tmp" }
NR==FNR{ print $6 >"first_column.tmp" }' TCGA-A*/t_data.ctab
然后将paste
它们与逗号分隔的文件放在一起(-d,
如果您想使用制表符,请将其删除):
paste -d, *.tmp
t_name,TCGA-A2-A0T3-01A,TCGA-A7-A4SA-01A,TCGA-A7-A6VW-01A
MSTRG.1.1,0.000000,0.00000,0.0000
MSTRG.10.1,0.284182,0.28418,0.2841
MSTRG.11.1,0.077194,0.07719,0.0771
ENST00000456328.2,0.000000,0.00000,0.0000
MSTRG.10.3,0.000000,0.00000,0.0000
MSTRG.11.2,0.051214,0.05121,0.0512
ENST00000450305.2,0.000000,0.00000,0.0000
MSTRG.10.5,0.007904,0.00790,0.0079
MSTRG.10.6,0.000000,0.00000,0.0000
MSTRG.10.7,0.000000,0.00000,0.0000
MSTRG.11.3,0.137788,0.13778,0.1377
答案2
您对 csv 输出满意吗?
find ballgown -name t_data.ctab | awk ' {
F=$0
print F " started"
split(F,P,"/")
FN= P[2]
TF[FN]=1
getline < F
while ((getline < F) > 0) {
TN[$6]=1
TV[FN ":" $6] = $NF
}
close(F)
print f " done"
}
END {
printf("tname")
for (F in TF) {
printf(", %s",F)
}
print ""
for (N in TN) {
printf("%s",N)
for (F in TF) {
printf(", %s",TV[F ":" N])
}
print ""
}
}
'
答案3
我将问题分为两个操作,如问题评论中所述。这是可能的,因为每个文件的第一列完全相同,并且每个文件具有相同的行数。
将自己定位在舞会礼服目录中:
cd ballgown
第一步,创建一个包含第一列的输出文件:
cut -f6 TCGA-A7-A6VW-01A/t_data.ctab > out.tab
大部分工作是通过find
和 的组合来完成的perl
:
find -iname t_data.ctab -exec perl -i.bak -lane 'if($.==1){$ARGV=~/([-\w]+)\/.*$/;$f=$1} if(1..eof&&($n=$.)){$a[$.]=$F[11];$a[1]=$f;next}; print "$_\t$a[$.-$n]"' {} out.tab \;
笔记:这是一种破坏性的行为;原始文件将保留并添加.bak
扩展名。
非破坏性版本,利用sponge
(也find
被循环替换for
):
for F in */t_data.ctab; do perl -lane 'if(1..eof&&($n=$.)){$a[$.]=$F[11];$a[1]=$ARGV=~s/([-\w]+)\/.*$/$1/r;next} print "$_\t$a[$.-$n]"' $F out.tab | sponge out.tab; done;
答案4
完全编程的解决方案,在PHP。
<?php
$filenames = glob('*/t_data.ctab');
foreach($filenames as $k=>$filename) {
$name = pathinfo($filename)['dirname'] . "\n";
$file = file($filename);
foreach ($file as $n => $line) {
$line = explode("\t", $line);
if ($n === 0) {
$line[11] = $name;
}
if ($k === 0) {
$out[$n] = $line[5] . "\t" . $line[11];
} else {
$out[$n] = trim($out[$n]) . "\t" . $line[11];
}
}
}
file_put_contents('out.tab', $out);
用法:
- 将自己定位在
ballgown
目录中 - 保存文件并命名
script.php
- 运行脚本
php script.php
out.tab
您将在文件中找到输出
笔记:
如果您需要有关如何安装和使用 PHP、脚本的作用以及如何针对特定需求进行调整的进一步说明,请告诉我。
这是相同的解决方案Python,因为评论中提到了该语言。这是我第一次写Python,所以请提出改进建议。
import os, glob
out = []
for k, filename in enumerate(glob.glob('*/t_data.ctab')):
with open(filename, 'r') as f:
file = f.readlines()
for n, line in enumerate(file):
line = line.split("\t")
if n == 0:
line[11] = os.path.dirname(filename) + "\n"
if k == 0:
out.append(line[5] + "\t" + line[11])
else:
out[n] = out[n].strip() + "\t" + line[11]
outfile = open('out.tab', 'w')
outfile.write("".join(out))
相同的方法,写成珀尔单行:
perl -lane '$a[$n].=($a[$n]?"":$F[5])."\t".($n<1?$ARGV=~s#([-\w]+)\/.*$#$1#r:$F[11]); $n=eof?0:$n+1}{print "$_" for @a' */t_data.ctab