【问题标题】:Remove long row of data points in Matlab在 Matlab 中删除长行数据点
【发布时间】:2018-08-01 18:20:02
【问题描述】:

我有一个坐标列表coord,绘制时看起来像这样:

我想从数据集中删除完全从 0 到 1 的长串点,如图所示,从 (0, 11) 开始,到 (1, 11) 结束,另一个开始于(0, 24) 并在 (1, 28) 处结束。

到目前为止,我已经尝试使用 kmeans 使用以下代码按高度对数据进行分组:

jet = colormap('jet');

amount = 20;
step = floor(numel(jet(:,1))/amount);
idxOIarr = cell(numel(terp));
scale = 100;

for ii = 1:numel(terp)
    figure;
    hold on;
    expandDat = [stretched{ii}(:,1), scale.*log(terp{ii}(:,2))];
    [idx, cent] = kmeans(expandDat(:,1:2), amount, 'Distance', 'cityblock');
    idxOIarr{ii} = idx;
    for jj = 1:amount
        scatter(stretched{ii}(idx == jj,1), FREQ(terp{ii}(idx == jj,2)), 10, jet(step*jj,:), 'filled');
    end
end

导致此图像: 尽管它确实很好地分隔了较高的行,但它会将中间的行分成两部分,并将从 (0,20) 开始的行与其下方的一些数据点分组。

还有其他方法可以对这些点进行分组和删除吗?

【问题讨论】:

  • 您想根据距离对点进行分组。使用 R-tree 找到每个点的最近邻居。这将为您提供一个图表,其中您认为“连接”的每两个点都由一条边连接。接下来,在图中找到从一侧延伸到另一侧的连通分量。
  • 嗨@CrisLuengo,感谢您的回复。如果你有时间,你能在解释的地方回答吗?我以前从未听说过 R-trees,并且不确定如何实施您的建议。

标签: matlab scatter-plot


【解决方案1】:

解决此问题的最有效方法是构建一个图,其中每个点都是一个顶点。您将您认为“连接”或“封闭”的点与边缘连接起来。因此,图将连接组件。现在你需要寻找从 0 到 1 整个范围的连通分量。

  1. 构建图表。使用 R-tree 查找邻居是最有效的。 Here are some suggestions。例如,您还可以使用 k-d 树。但是,这并不是绝对必要的,如果没有适当的空间索引结构,它会变得非常慢,因为您必须比较每对点之间的距离。

    给定一个 Nx2 矩阵 coord,您可以找到每对之间的平方距离:

    D = sum((reshape(coord,[],1,2) - reshape(coord,1,[],2)).^2,3);
    

    (再次注意,如果 N 很大,这会很昂贵,在这种情况下,使用 R-tree 会显着加快速度)。 D(i,j) 是索引为ij 的点之间的距离(即coord(i,:)coord(j,:)

    接下来,构建图,G,如果G(i,j)==1,则连接节点ijG 是一个对称矩阵:

    G = D <= max_distance;
    
  2. 查找连接的组件。连接的组件只是一组节点,您可以通过沿边相互访问。你不需要找到所有的连通分量,你只需要找到具有x=0的点集,并从每个点开始,递归地访问其连通分量中的所有元素,看看你是否可以到达一个点x=1.

    下面的代码没有经过测试,但它提供了一个起点:

    start_indices = find(coord(:,1)==0);  % Is exact equality appropriate here?
    end_indices = find(coord(:,1)==1);
    to_remove = [];
    visited = false(size(coord,1), 1);
    for ii=start_indices.'
       % For each point with x=0, see if we can reach any of the points at x=1
       [res, visited] = can_reach(ii, end_indices, G, visited);
       if res
          % For this point we can, remove it!
          to_remove(end+1) = ii;
       end
    end
    
    % Iterative function to visit all nodes in a connected component
    function [res, visited] = can_reach(start, end_indices, G, visited)
       visited(start) = true;
       if any(start==end_indices)
          % We've reach an end point, stop iterating and return true.
          res = true;
          return;
       end
       next = find(G(start,:));  % find neighbors
       next(visited(next)) = []; % remove visited neighbors
       for ii=next
          [res, visited] = can_reach(ii, end_indices, G, visited);
          if res
             % Yes, we can visit an end point, stop iterating now.
             return
          end
       end
    end
    

【讨论】:

  • 感谢您的回答。我在理解如何从 x-y 坐标到图表上的节点时遇到了一些麻烦。如何找到ij
  • 好的,我相信我现在明白了;节点号是坐标的索引。如果这不正确,请纠正我。
  • @kmarx:确实,coord(i,:) 的点是图中的节点i。您对遍历每个连接组件所需的迭代算法是否满意?
  • 我尝试实现它,但遇到了一些麻烦。如果您为解决方案的第 2 步提供更详细的概述,我们将不胜感激。
  • @kmarx:更多的是代码大纲,我还没有尝试运行它。我希望这对您来说是一个很好的起点。
猜你喜欢
  • 2019-04-27
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 2017-11-27
相关资源
最近更新 更多