我有这个文件(稀疏矩阵):
PC.354 OTU1 6
PC.354 OTU2 1
PC.356 OTU0 4
PC.356 OTU2 7
PC.356 OTU3 3
我想要这样的输出(密集矩阵-经典 .biom 表):
OTU_ID PC.354 PC.355 PC.356
OTU0 0 0 4
OTU1 6 0 0
OTU2 1 0 7
OTU3 0 0 3
我如何使用 awk/perl/sed 来做到这一点?我发现了一个关于 R 包(xtabs/tidyr)的类似问题,但我不习惯。
答案1
在 Perl 中:
#!/usr/bin/perl
my (%hotu, %hpc)=();
while(<>){
my($pc,$otu,$v)=split;
$hpc{$pc}=1;
($hotu{$otu} or $hotu{$otu}={})->{$pc}+=$v;
}
#headers
my @apc = sort keys %hpc;
print join ("\t", 'OTU_ID', @apc) . "\n";
#values
foreach my $otu (sort keys %hotu) {
print join ("\t", $otu, map {$_=0 unless defined; $_} @{$hotu{$otu}}{@apc}) . "\n";
}
答案2
在awk
:
{ data[$2, $1] = $3; }
END {
split("OTU0 OTU1 OTU2 OTU3", rows);
split("OTU_ID PC.354 PC.355 PC.356", cols);
for (i = 1; i <= 4; i++) {
printf("%10s", cols[i]);
}
print "";
for (i = 1; i <= 4; i++) {
printf("%-10s", rows[i]);
for (j = 2; j <= 4; j++) {
item = data[rows[i], cols[j]];
if (!item) { item = "0" };
printf("%10s", item);
}
print "";
}
}
请注意,我已明确包含示例输出中的所有行和列。如果数据实际上包含所有行和列(示例数据不包含这些),则没有必要这样做。