3

我有一个数组,其中包含许多 0 到 360 之间的值(如圆圈中的度数),但分布不均:

1,45,46,47,48,49,50,51,52,53,54,55,100,120,140,​​188,210,280,355

现在我需要将这些值减少到例如 4,但要尽可能均匀地分布值。

怎么做?

谢谢,扬

4

2 回答 2

3

把数字放在一个圆圈上,就像一个时钟。现在构建一个逻辑十字,比如在 12、3、6 和 9 点钟。将 12 放在第一个数字上。现在找出最接近 3 点、6 点和 9 点的数字,并在第一个数字旁边记录这三个数字的距离之和。

通过顺时针旋转十字的顶部(12 点钟点)进行迭代,直到它与下一个数字完全对齐。再次测量最接近的数字与其他三个交叉点的距离,并将该分数记录在当前 12 点钟数字旁边。

重复直到你的 12 点一直旋转到原来的 3 点,此时你就完成了。分配给它的总和最低的数字决定了获胜的配置。

该解决方案可推广到任何值范围的 R您希望将集合减少到的任意数量的最终点 N。“十字架”上的每个点彼此相距 R/N,您只需旋转直到十字架的顶部到达下一个手臂在原始位置的位置。因此,如果您想要 6 个点,您将有一个 6 点交叉,每个 60 度,而不是一个 4 点交叉,每个 90 度。如果您的范围不同,您仍然执行相同的操作。这样你就不需要物理时钟和交叉来实现这个算法:它适用于任何 R 和 N。

从 Perl 的角度来看,我对这个答案感到很糟糕,因为我没有设法在解决方案中包含任何美元符号。:)

于 2010-11-23T02:20:02.980 回答
1

使用聚类算法将数据划分为均匀分布的分区。然后从每个集群中获取一个随机值。如下$datafile所示:

1   1
45  45
46  46
...
210 210
280 280
355 355

第一列是标签,第二列是数据。运行以下内容$K = 4

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->[int rand( @$cluster - 1)];
}

use YAML; print Dump \%clusters;

返回这个:

120: 120
199: 188
317.5: 355
45.9166666666667: 46

第一列是集群的中心,第二列是从该集群中选择的值。中心之间的距离应该根据期望最大化算法最大化

于 2010-11-23T07:24:22.133 回答