![如何计算列的(加权)多数?](https://linux22.com/image/4033/%E5%A6%82%E4%BD%95%E8%AE%A1%E7%AE%97%E5%88%97%E7%9A%84%EF%BC%88%E5%8A%A0%E6%9D%83%EF%BC%89%E5%A4%9A%E6%95%B0%EF%BC%9F.png)
我有两个文件:第一个文件包含第一列是 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
第二步,我还想计算不同线路的加权投票。在这种情况下,这将是
(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);