在Matlab中删除长行数据点
Remove long row of data points in Matlab
我有一个坐标列表,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) 开始的行与一些数据点分组在它下面。
有没有其他方法可以对这些点进行分组和删除?
解决这个问题的最有效方法是构建一个图,其中每个点都是一个顶点。您将您认为 "connected" 或 "closed" 的点与一条边连接起来。因此,该图将连接组件。现在您需要寻找跨越从 0 到 1 的整个范围的连通分量。
构建图形。使用 R 树查找邻居最有效。 Here are some suggestions。例如,您还可以使用 k-d 树。然而,这并不是绝对必要的,如果没有适当的空间索引结构,它会变得非常慢,因为您必须比较每对点之间的距离。
给定一个 Nx2 矩阵 coord
,你可以找到每对之间的平方距离:
D = sum((reshape(coord,[],1,2) - reshape(coord,1,[],2)).^2,3);
(再次注意,如果 N 很大,这会很昂贵,在这种情况下,使用 R 树会显着加快速度)。 D(i,j)
是索引为 i
和 j
的点之间的距离(即 coord(i,:)
和 coord(j,:)
.
接下来,构建图,G
,如果G(i,j)==1
,节点i
和j
是连接的。 G
是对称矩阵:
G = D <= max_distance;
求连通分量。连接的组件只是一组节点,您可以通过跟随边从彼此到达这些节点。你真的不需要找到所有连通分量,你只需要找到具有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
我有一个坐标列表,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
生成此图像:
有没有其他方法可以对这些点进行分组和删除?
解决这个问题的最有效方法是构建一个图,其中每个点都是一个顶点。您将您认为 "connected" 或 "closed" 的点与一条边连接起来。因此,该图将连接组件。现在您需要寻找跨越从 0 到 1 的整个范围的连通分量。
构建图形。使用 R 树查找邻居最有效。 Here are some suggestions。例如,您还可以使用 k-d 树。然而,这并不是绝对必要的,如果没有适当的空间索引结构,它会变得非常慢,因为您必须比较每对点之间的距离。
给定一个 Nx2 矩阵
coord
,你可以找到每对之间的平方距离:D = sum((reshape(coord,[],1,2) - reshape(coord,1,[],2)).^2,3);
(再次注意,如果 N 很大,这会很昂贵,在这种情况下,使用 R 树会显着加快速度)。
D(i,j)
是索引为i
和j
的点之间的距离(即coord(i,:)
和coord(j,:)
.接下来,构建图,
G
,如果G(i,j)==1
,节点i
和j
是连接的。G
是对称矩阵:G = D <= max_distance;
求连通分量。连接的组件只是一组节点,您可以通过跟随边从彼此到达这些节点。你真的不需要找到所有连通分量,你只需要找到具有
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