计算xy点密度最高的中心点

时间:2015-10-29 13:31:21

标签: javascript arrays coordinate-systems

我有一个方格(200 x 200)。我希望用户能够在这个空间中对他们下一个想要的对象位置进行投票。当用户投票时,我将XY位置添加到数组中。

目前正在寻找"中奖"位置我只取平均值X和Y的平均值,但我发现的是获胜位置倾向于围绕该区域的中间(自然因为它是平均值!)。

Average

白色=投票,黄色="赢得" XY点

我最喜欢的是,如果它找到了最密集的投票区域,并在中间选择了一个点。

单一的分散投票不会像平均值那样将胜利位置拉离密集区域。

这可能吗?

示例数组

[ { x: 39, y: 28 },
  { x: 69, y: 33 },
  { x: 51, y: 51 },
  { x: 14, y: 63 },
  { x: 75, y: 140 },
  { x: 171, y: 68 },
  { x: 140, y: 53 },
  { x: 173, y: 150 },
  { x: 123, y: 179 },
  { x: 103, y: 150 },
  { x: 145, y: 119 },
  { x: 92, y: 85 },
  { x: 58, y: 49 },
  { x: 28, y: 65 },
  { x: 41, y: 39 },
  { x: 46, y: 41 },
  { x: 49, y: 51 },
  { x: 43, y: 55 },
  { x: 35, y: 48 },
  { x: 29, y: 31 },
  { x: 68, y: 22 },
  { x: 58, y: 39 } ]

3 个答案:

答案 0 :(得分:4)

解决方案可以是为每个点计算从它到所有其他点的距离之和。总和最小的点应该是密度最高的区域的中心。

答案 1 :(得分:2)

这实际上非常简单 - 将所有X组合成1个变量,并将其除以X的数量。同样适用于y:

var totalX = 0, totalY = 0, avgX, avgY;

var coords = [ { x: 39, y: 28 },
    { x: 69, y: 33 },
    { x: 51, y: 51 },
    { x: 14, y: 63 },
    { x: 75, y: 140 },
    { x: 171, y: 68 },
    { x: 140, y: 53 },
    { x: 173, y: 150 },
    { x: 123, y: 179 },
    { x: 103, y: 150 },
    { x: 145, y: 119 },
    { x: 92, y: 85 },
    { x: 58, y: 49 },
    { x: 28, y: 65 },
    { x: 41, y: 39 },
    { x: 46, y: 41 },
    { x: 49, y: 51 },
    { x: 43, y: 55 },
    { x: 35, y: 48 },
    { x: 29, y: 31 },
    { x: 68, y: 22 },
    { x: 58, y: 39 } ]

for (var i = 0; i <= coords.length; i++) {
    totalX += coords[i].x;
    totalY += coords[i].y;
}

avgX = totalX / coords.length;
avgY = totalY / coords.length;

在行动中见到harrr(lol at ID):https://jsfiddle.net/harr55d2/

编辑:这不是正确的答案,对不起,误读了你的问题。

你可以做的是,从这个平均位置计算从那里到所有点的距离。你会从那里得到一些数字。如果你计算了距离的平均值,我认为你会接近你想要的点。

另一种方法是以20x20的块扫描200x200区域(或者某些东西,也许圆圈效果最好)并计算其中的所有投票。得票最多的人获胜。

编辑:另一种方法;

从平均点开始每次投票的距离。那就是&#34;得分&#34;或者&#34;体重&#34;进行一定投票。然后,您可以看到最接近平均值的投票正在加权最好的&#34;。如果你抓住我的漂移。

答案 2 :(得分:1)

好吧,我不是只发表一个想法,而是发布实际代码。希望你能看出它是否适合你。

您的问题基本上属于集群分析领域。您希望识别数据集中存在的不同数据组以及哪些数据组形成群集。 https://en.wikipedia.org/wiki/Cluster_analysis

幸运的是,这个问题已经有一些方法需要解决,甚至还有一个NPM软件包可以让你执行一些熟知的集群分析工具。

我已经选择了DBSCAN来解决你的一系列问题,如果你觉得自己需要别的东西,我很幸运能尝试另一种算法。 https://en.wikipedia.org/wiki/DBSCAN

我使用过NPM的密度聚类库。 https://github.com/LukaszKrawczyk/density-clustering

DBSCAN 的任意参数对于邻域半径 20 5 表示最小点数被视为“群集” “

代码是NPM包的github页面中给出的示例的修改版本。

var sample = [ { x: 39, y: 28 },
  { x: 69, y: 33 },
  { x: 51, y: 51 },
  { x: 14, y: 63 },
  { x: 75, y: 140 },
  { x: 171, y: 68 },
  { x: 140, y: 53 },
  { x: 173, y: 150 },
  { x: 123, y: 179 },
  { x: 103, y: 150 },
  { x: 145, y: 119 },
  { x: 92, y: 85 },
  { x: 58, y: 49 },
  { x: 28, y: 65 },
  { x: 41, y: 39 },
  { x: 46, y: 41 },
  { x: 49, y: 51 },
  { x: 43, y: 55 },
  { x: 35, y: 48 },
  { x: 29, y: 31 },
  { x: 68, y: 22 },
  { x: 58, y: 39 } ];


/* Transform your dataset to the format expected by the library */
var dataset = [];

for(var i=0; i<sample.length; i++){
   dataset.push([sample[i].x, sample[i].y]);
}

var clustering = require('density-clustering');
var dbscan = new clustering.DBSCAN();
/* parameters: 
    20 - neighborhood radius
    5 - number of points in neighborhood to form a cluster
*/
var clusters = dbscan.run(dataset, 20, 5);

if(clusters.length > 0){

    /* Find the biggest cluster */
    var biggestCluster = clusters[0];

    for(i=1;i<clusters.length;i++){

        if(cluster[i].length > biggestCluster.length){
            biggestCluster = cluster[i];    
        }
    }

    /* The output of the library contains the indexes of the points in the cluster, not the coordinates, so we need to get the point from the dataset */
    var clusterPoints = [];
    var sumx = 0;
    var sumy = 0;

    for(i=0;i<biggestCluster.length;i++){
       var point = dataset[biggestCluster[i]];
       clusterPoints.push(point);

       /* It's also a good opportunity to cumulate x and y so we can get the average */
       sumx+=point[0];
       sumy+=point[1];
    }

    console.log('Cluster:', clusterPoints);    
    console.log('Center:', sumx/clusterPoints.length, sumy / clusterPoints.length);
}
else{
    console.log('No clusters');
}

该程序的输出将是:

Cluster: [ [ 51, 51 ], [ 58, 49 ], [ 41, 39 ], [ 46, 41 ], [ 49, 51 ], [ 43, 55 ],  [ 35, 48 ],  [ 58, 39 ], [ 69, 33 ],  [ 39, 28 ], [ 29, 31 ], [ 28, 65 ], [ 68, 22 ] ]

Center: 47.23076923076923 42.46153846153846