我在一个目录中有12个文件,每个文件有4列。第一列是基因名称,其余3是计数列。所有文件都在同一目录中。我想为每个文件提取1,4列(总共12个文件)并将它们粘贴到一个输出文件中,因为第一列对于每个文件都是相同的,输出文件应该只有第一列一次,其余的将是然后是每个文件的第4列。每个文件的第一列是相同的。我不想在这里使用R.我是awk的忠实粉丝。所以我尝试了类似下面的东西,但它不起作用
我的输入文件看起来像 输入文件1
ZYG11B 8267 16.5021 2743.51
ZYG11A 4396 0.28755 25.4208
ZXDA 5329 2.08348 223.281
ZWINT 1976 41.7037 1523.34
ZSCAN5B 1751 0.0375582 1.32254
ZSCAN30 4471 4.71253 407.923
ZSCAN23 3286 0.347228 22.9457
ZSCAN20 4343 3.89701 340.361
ZSCAN2 3872 3.13983 159.604
ZSCAN16-AS1 2311 1.1994 50.9903
输入文件2
ZYG11B 8267 18.2739 2994.35
ZYG11A 4396 0.227859 19.854
ZXDA 5329 2.44019 257.746
ZWINT 1976 8.80185 312.072
ZSCAN5B 1751 0 0
ZSCAN30 4471 9.13324 768.278
ZSCAN23 3286 1.03543 67.4392
ZSCAN20 4343 3.70209 318.683
ZSCAN2 3872 5.46773 307.038
ZSCAN16-AS1 2311 3.18739 133.556
输入文件3
ZYG11B 8267 20.7202 3593.85
ZYG11A 4396 0.323899 29.8735
ZXDA 5329 1.26338 141.254
ZWINT 1976 56.6215 2156.05
ZSCAN5B 1751 0.0364084 1.33754
ZSCAN30 4471 6.61786 596.161
ZSCAN23 3286 0.79125 54.5507
ZSCAN20 4343 3.9199 357.177
ZSCAN2 3872 5.89459 267.58
ZSCAN16-AS1 2311 2.43055 107.803
上述所需的输出
ZYG11B 2743.51 2994.35 3593.85
ZYG11A 25.4208 19.854 29.8735
ZXDA 223.281 257.746 141.254
ZWINT 1523.34 312.072 2156.05
ZSCAN5B 1.32254 0 1.33754
ZSCAN30 407.923 768.278 596.161
ZSCAN23 22.9457 67.4392 54.5507
ZSCAN20 340.361 318.683 357.177
ZSCAN2 159.604 307.038 267.58
ZSCAN16-AS1 50.9903 133.556 107.803
这里你可以看到每个文件和第4列的第一列,因为每个文件的第一列是相同的,所以我只想保留一次,休息时,每个文件的第4列都会有。我刚刚显示了3个文件。它应该同时适用于目录中的所有文件,因为所有文件都有类似的命名约定,如file1_quant.genes.sf file2_quant.genes.sf,file3_quant.genes.sf
每个文件都有相同的第一列,但在休息列中有不同的计数。我的想法是创建一个输出文件,该文件应该包含所有文件的第1列和第4列。
awk '{print $1,$2,$4}' *_quant.genes.sf > genes.estreads
任何抬头?
答案 0 :(得分:3)
如果我理解正确的话,你要找的是每个键一行,从多个文件中整理出来。
此作业所需的工具是关联数组。我认为awk
可以,但我不是100%肯定。我可能会在perl中解决它:
#!/usr/bin/perl
use strict;
use warnings;
# an associative array, or hash as perl calls it
my %data;
#iterate the input files (sort might be irrelevant here)
foreach my $file ( sort glob("*_quant.genes.sf") ) {
#open the file for reading.
open( my $input, '<', $file ) or die $!;
#iterate line by line.
while (<$input>) {
#extract the data - splitting on any whitespace.
my ( $key, @values ) = split;
#add'column 4' to the hash (of arrays)
push( @{$data{$key}}, $values[2] );
}
close($input);
}
#start output
open( my $output, '>', 'genes.estreads' ) or die;
#sort, because hashes are explicitly unordered.
foreach my $key ( sort keys %data ) {
#print they key and all the elements collected.
print {$output} join( "\t", $key, @{ $data{$key} } ), "\n";
}
close($output);
使用上面指定的数据,这会产生:
ZSCAN16-AS1 50.9903 133.556 107.803
ZSCAN2 159.604 307.038 267.58
ZSCAN20 340.361 318.683 357.177
ZSCAN23 22.9457 67.4392 54.5507
ZSCAN30 407.923 768.278 596.161
ZSCAN5B 1.32254 0 1.33754
ZWINT 1523.34 312.072 2156.05
ZXDA 223.281 257.746 141.254
ZYG11A 25.4208 19.854 29.8735
ZYG11B 2743.51 2994.35 3593.85
答案 1 :(得分:1)
以下是您在awk
中执行此操作的方法:
awk 'BEGIN{FS = " "};{print $1, $4}' *|awk 'BEGIN{FS = " "};{temp = x[$1];x[$1] = temp " " $2;};END {for(xx in x) print xx,x[xx]}'
看起来很神秘,我只是使用关联数组。
<小时/> 以下是解决方案:
只需打印键和值,每行一个。
print $1, $2
将数据存储在关联数组中,不断更新
temp = x[$1];x[$1] = temp " " $2;}
显示:
for(xx in x) print xx,x[xx]
示例运行:
[cloudera@quickstart test]$ cat f1
A k1
B k2
[cloudera@quickstart test]$ cat f2
A k3
B k4
C k1
[cloudera@quickstart test]$ awk 'BEGIN{FS = " "};{print $1, $2}' *|awk 'BEGIN{FS = " "};{temp = x[$1];x[$1] = temp " " $2;};END {for(xx in x) print xx,x[xx]}'
A k1 k3
B k2 k4
C k1
作为旁注,该方法应该让人联想到Map Reduce范例。
答案 2 :(得分:1)
awk '{E[$1]=E[$1] "\t" $4}END{for(K in E)print K E[K]}' *_quant.genes.sf > genes.estreads
订单是读取文件时的外观顺序(因此通常基于1个已读取的文件)
答案 3 :(得分:0)
如果所有文件中的第一列相同,则可以使用paste
:
paste <(tabify f1 | cut -f1,4) \
<(tabify f2 | cut -f4) \
<(tabify f3 | cut -f4)
tabify
将连续空格更改为标签:
sed 's/ \+/\t/g' "$@"
和f1,f2,f3是输入文件的名称。
答案 4 :(得分:0)
以下是在Perl中执行此操作的另一种方法:
perl -lane '$data{$F[0]} .= " $F[3]"; END { print "$_ $data{$_}" for keys %data }' input_file_1 input_file_2 input_file_3
答案 5 :(得分:0)
这是使用awk执行此操作的另一种方法。它支持使用多个文件。
awk 'FNR==1{f++}{a[f,FNR]=$1}{b[f,FNR]=$4}END { for(x=1;x<=FNR;x++){printf("%s ",a[1,x]);for(y=0;y<=ARGC;y++)printf("%s ",b[y,x]);print ""}}' input1.txt input2.txt input3.txt
该行代码,给出以下输出
ZYG11B 2743.51 2994.35 3593.85
ZYG11A 25.4208 19.854 29.8735
ZXDA 223.281 257.746 141.254
ZWINT 1523.34 312.072 2156.05
ZSCAN5B 1.32254 0 1.33754
ZSCAN30 407.923 768.278 596.161
ZSCAN23 22.9457 67.4392 54.5507
ZSCAN20 340.361 318.683 357.177
ZSCAN2 159.604 307.038 267.58
ZSCAN16-AS1 50.9903 133.556 107.803