我想分割这些数据,

ID x    y
1  2.5  3.5
1  85.1 74.1
2  2.6  3.4
2  86.0 69.8
3  25.8 32.9
3  84.4 68.2
4  2.8  3.2
4  24.1 31.8
4  83.2 67.4

我能够和他们的伴侣配对,
ID x    y    ID x    y
1  2.5  3.5  1  85.1 74.1
2  2.6  3.4  2  86.0 69.8
             3  25.8 32.9
             4  24.1 31.8

但是,您会注意到ID 4中的某些新行被放错了位置,因为它只是被添加到接下来的几行中。我想适当地拆分它们,而不必使用我已经在使用的复杂逻辑...有人可以给我一个算法或想法吗?

它看起来应该像
ID x    y    ID x    y      ID x    y
1  2.5  3.5  1  85.1 74.1   3  25.8 32.9
2  2.6  3.4  2  86.0 69.8   4  24.1 31.8
4  2.8  3.2  3  84.4 68.2
             4  83.2 67.4

最佳答案

看来您的问题确实与聚类有关,并且ID列与确定哪个点对应于哪个点无关。

常见的算法是k-means clustering。但是,您的问题意味着您不预先知道群集的数量。这使事情变得复杂,并且在StackOverflow上已经有很多关于此问题的问题:

  • Kmeans without knowing the number of clusters?
  • compute clustersize automatically for kmeans
  • How do I determine k when using k-means clustering?
  • How to optimal K in K - Means Algorithm
  • K-Means Algorithm

  • 不幸的是,对此没有“正确”的解决方案。一个特定问题中的两个群集实际上可以视为另一个问题中的一个群集。这就是为什么您必须自己决定的原因。

    但是,如果您正在寻找简单的东西(可能不准确),则可以使用欧几里得距离作为度量。计算点之间的距离(例如,使用 pdist ),并对距离低于特定阈值的点进行分组。


    %// Sample input
    A = [1,  2.5,  3.5;
         1,  85.1, 74.1;
         2,  2.6,  3.4;
         2,  86.0, 69.8;
         3,  25.8, 32.9;
         3,  84.4, 68.2;
         4,  2.8,  3.2;
         4,  24.1, 31.8;
         4,  83.2, 67.4];
    
    %// Cluster points
    pairs = nchoosek(1:size(A, 1), 2); %// Rows of pairs
    d = sqrt(sum((A(pairs(:, 1), :) - A(pairs(:, 2), :)) .^ 2, 2)); %// d = pdist(A)
    thr = d < 10;                      %// Distances below threshold
    kk = 1;
    idx = 1:size(A, 1);
    C = cell(size(idx));               %// Preallocate memory
    while any(idx)
         x = unique(pairs(pairs(:, 1) == find(idx, 1) & thr, :));
         C{kk} = A(x, :);
         idx(x) = 0;                   %// Remove indices from list
         kk = kk + 1;
    end
    C = C(~cellfun(@isempty, C));      %// Remove empty cells
    

    结果是一个单元格数组C,每个单元格代表一个集群:
    C{1} =
        1.0000    2.5000    3.5000
        2.0000    2.6000    3.4000
        4.0000    2.8000    3.2000
    
    C{2} =
        1.0000   85.1000   74.1000
        2.0000   86.0000   69.8000
        3.0000   84.4000   68.2000
        4.0000   83.2000   67.4000
    
    C{3} =
        3.0000   25.8000   32.9000
        4.0000   24.1000   31.8000
    

    注意,这种简单的方法具有将簇半径限制为阈值的缺陷。但是,您需要一个简单的解决方案,因此请记住,随着向该算法添加更多“集群逻辑”,该解决方案会变得复杂。

    关于c++ - 知道其通用ID的拆分数据,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14458526/

    10-12 18:06