在新的2D数组中对2D数组进行排序(K均值聚类) [英] Sorting 2D array in new 2D array (K-means clustering)

查看:78
本文介绍了在新的2D数组中对2D数组进行排序(K均值聚类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为输入,我有一个二维数组PointXY[][] clusters,如下所示:

As input I have a 2D array PointXY[][] clusters, which looks like this:

[[23.237633,53.78671], [69.15293,17.138134], [23.558687,45.70517]] . . .
[[47.851738,16.525734], [47.802097,16.689285], [47.946404,16.732542]]
[[47.89601,16.638218], [47.833263,16.478987], [47.88203,16.45793]]
[[47.75438,16.549816], [47.915512,16.506475], [47.768547,16.67624]]
.
.
.

因此,数组中的元素的定义类型为PointXY[],如下所示:

So elements in array are of type PointXY[] defined like this:

public PointXY(float x, float y) {
    this.x = x;
    this.y = y;
}

我想做的是对输入簇进行排序,然后对数组PointXY[][] clustersSorted进行排序,以便将簇中的每个PointXY(第一行除外)与第一行的每个值进行比较. 换句话说,下面图片中蓝色设置的元素将与红色圈出的每个值进行比较. 因此,我想比较从2行开始的每个值与第一行中的每个值.

what I would like to do is sort input clusters and write sorted to array PointXY[][] clustersSorted so that each PointXY (exept first row) in clusters gets compared to every value of first row. In other words the elements from the blue set on picture below get compared to every value circled by red. So I would like to compare each value from 2. Row onwards to every value in first row.

比较是通过调用Euclidian函数完成的.

Comparing is done by calling Euclidian function.

public double euclidian(PointXY other) {
    return Math.sqrt(Math.pow(this.x - other.x, 2)
            + Math.pow(this.y - other.y, 2));
}

输出应该是相同类型的2D数组,但是在每个红色圆圈点下(在输出数组中的相同位置处都保持相同)应该是蓝色部分中距离红色圆圈值最近(按欧几里德距离)的点

Output should be of the same type 2D array but under each red circled point (which stays the same in the same place in output array) should be points from blue part that are closest (by euclidean distance) to the red circled value.

这是K-Means聚类的数据结构,因此每个聚类是一列(绿色圆圈),第一个点是聚类的中心(红色圆圈),列中的所有其他点(黄色圆圈)是分配给中心的点.

So it's a data structure for K-Means clustering, so that each cluster is a column (circled green) and the first point is a center (circled red) of cluster and all the other points (circled in yellow) in column are points assigned to center.

所以问题是如何遍历输入数组簇,按所述比较值,并将其写入数组clustersSorted.

So the question is how to iterate over input array clusters, compare values as described, and write them into array clustersSorted.

我想计算蓝色圆圈组中每个点与红色圆圈中每个值之间的欧几里得距离.然后根据最小欧氏距离对它们进行排序.因此,在输出数组clustersSorted中,蓝色圆圈组中的每个点都将在红色圆圈中的最接近点之下.

I would like to calculate euclidean distance between each point in blue circled set with every value circled in red. And then sort them based on minimal euclidean distance. So in output array clustersSorted each point from blue circled set would be under closest point circled in red.

推荐答案

查看其他答案:对从第二行距第一行最近的中心点

要按列对对象的二维数组进行排序,您可以先转置该数组并对每一行进行排序,然后对它进行转置.要使用自定义比较器对从第二个元素开始的元素行与第一个元素之间的距离进行排序-您可以使用

To sort a 2d array of objects by columns, you can first transpose this array and sort each row, and then transpose it back. To sort a row of elements starting from the second one by the distance from the first one with a custom comparator - you can use Arrays.sort(T[],int,int,Comparator) method:

int m = 4;
int n = 3;
PointXY[][] clusters = {
        {new PointXY(23.237633, 53.78671),
                new PointXY(69.15293, 17.138134),
                new PointXY(23.558687, 45.70517)},
        {new PointXY(47.851738, 16.525734),
                new PointXY(47.802097, 16.689285),
                new PointXY(47.946404, 16.732542)},
        {new PointXY(47.89601, 16.638218),
                new PointXY(47.833263, 16.478987),
                new PointXY(47.88203, 16.45793)},
        {new PointXY(47.75438, 16.549816),
                new PointXY(47.915512, 16.506475),
                new PointXY(47.768547, 16.67624)}};

// transpose a matrix
PointXY[][] transposed = new PointXY[n][m];
IntStream.range(0, n).forEach(i ->
        IntStream.range(0, m).forEach(j ->
                transposed[i][j] = clusters[j][i]));

// sort each line starting from the second
// element by the distance from the first element
Arrays.stream(transposed).forEach(cluster ->
        Arrays.sort(cluster, 1, cluster.length,
                Comparator.comparingDouble(point ->
                        Math.sqrt(Math.pow(cluster[0].x - point.x, 2)
                                + Math.pow(cluster[0].y - point.y, 2)))));

// transpose a matrix back
PointXY[][] clustersSorted = new PointXY[m][n];
IntStream.range(0, m).forEach(i ->
        IntStream.range(0, n).forEach(j ->
                clustersSorted[i][j] = transposed[j][i]));

// output
Arrays.stream(clustersSorted).map(Arrays::toString).forEach(System.out::println);

[23.237633,53.78671, 69.15293,17.138134, 23.558687,45.70517]
[47.75438,16.549816, 47.915512,16.506475, 47.768547,16.67624]
[47.89601,16.638218, 47.833263,16.478987, 47.946404,16.732542]
[47.851738,16.525734, 47.802097,16.689285, 47.88203,16.45793]


PointXY应该看起来像这样:


Class PointXY should look like this:

public class PointXY {
    double x, y;

    public PointXY(double x, double y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return x + "," + y;
    }
}

这篇关于在新的2D数组中对2D数组进行排序(K均值聚类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆