2つのファイルがあります。最初のファイルには、最初の列がIDで、残りの列が投票された行が含まれています。
3242 -1 1 -1 1 1 1
最初のステップとして、ほとんどのIDを計算したいと思います。上記の例では、賛成投票が反対投票より多いため、投票は 1 です。次の行を使用して結果を出力ファイルに保存したいと思います。
3242 1
また、その投票の「重み」を含むファイルもあります。
3242 0.9 0.1 0.9 0.2 0.1 0.2
2番目のステップとして、さまざまな行の重み投票を計算したいと思います。この場合、
(0.9*-1)+(0.1*1)+(0.9*-1)+(0.2*1)+(0.1*1)+(0.2*1)=-1.2
結果は否定的であるため、投票は-1にする必要があります。もう一度言いますが、各行にIDと結果投票を含む出力ファイルにこれを保存したいと思います。
awkやPerlを使ってこれを達成できますか?
答え1
#!/usr/bin/perl
use List::MoreUtils qw(pairwise);
use List::Util qw(sum);
use strict;
sub read_file {
my ($filename) = @_;
open F, '<', $filename or die "Could not open $filename: $!";
my %data;
while (<F>) {
my ($id, @data) = split;
$data{$id} = \@data;
}
close F;
return %data;
}
sub output_file {
my ($filename, %data) = @_;
open F, '>', $filename or die "Could not open $filename: $!";
for (sort keys %data) {
print F "$_\t$data{$_}\n";
}
close F;
}
my %votes = read_file 'votes.tsv';
my %weights = read_file 'weights.tsv';
my %unweighted;
while (my ($id, $data) = each(%votes)) {
my $sum = List::Util::sum(@$data);
$unweighted{$id} = $sum < 0 ? -1 :
$sum > 0 ? +1 : 0;
}
output_file('unweighted.tsv', %unweighted);
my %weighted;
while (my ($id, $data) = each(%weights)) {
my $dot_prod = sum(pairwise { $a * $b } @{$votes{$id}}, @$data);
$weighted{$id} = $dot_prod < 0 ? -1 :
$dot_prod > 0 ? +1 : 0;
}
output_file('weighted.tsv', %weighted);