0

私はこのようなデータを持っています

#Status value
TP       5.000
TP       3.000
TP       3.000
TN       10.000
TP       2.000
TP       9.000
TN       1.000
TP       9.000
TN       1.000

やりたいことは、 で指定された間隔に基づいてステータスをクラスター化することですvalue。その間隔を1-3, 4-6, 7-9, 10-12, etc ..(つまり、ビン サイズ 3) とします。

次のように配列のハッシュを取得したいと考えています。

my %hoa = (
'1-3' => [TP,TP,TP,TN,TN],
'4-6' => [TP],
'7-9' => [TP,TP],
'10-12' => [TN]);

それを達成する方法は何ですか?

更新: 7-9ysth のおかげで、 の HoA を修正しました。

4

2 に答える 2

2

ysth の答えは私も最初に思いついたもので、彼は正しいアプローチをしていると思います。

提案を残しておきたいのですが、クラスタリングアルゴリズムを使用して、将来的に保証される方法でこれを行うことができます(たとえば、データが多次元になる場合)。たとえば、K-means は、あなたのような 1D データでも問題なく機能します。

例えば:

use strict; use warnings;
use Algorithm::KMeans;

my $datafile = $ARGV[0] or die;
my $K        = $ARGV[1] or 0;
my $mask     = 'N1';

my $clusterer = Algorithm::KMeans->new(
    datafile => $datafile,
    mask     => $mask,
    K        => $K,
    terminal_output => 0,
);

$clusterer->read_data_from_file();

my ($clusters, $cluster_centers) = $clusterer->kmeans();

my %clusters;

while (@$clusters) {

    my $cluster = shift @$clusters;
    my $center  = shift @$cluster_centers;

    $clusters{"@$center"} = $cluster;
}

use YAML; print Dump \%clusters;
于 2010-11-08T06:57:33.340 に答える
2

間隔を決定するためにコードを抽象化します。

sub interval {
    my ($val) = @_;
    my $i = int( ( $val + 2 ) / 3 );
    my $interval = sprintf( '%d-%d', $i * 3 -2, $i * 3 );
    return $interval;
}

my %hoa;
while ( my $line = <> ) {
    next if $line =~ /^#/;
    my ($status, $value) = split ' ', $line;
    push @{ $hoa{ interval($value) } }, $status;
}

use Data::Dumper;
print Dumper \%hoa;

(これは、あなたが示すように1つではなく、7-9で2つのTPを取得します).

于 2010-11-08T03:35:23.477 に答える