删除重复项会删除太多点

时间:2018-07-11 14:25:23

标签: arrays matlab

我正在尝试从一组键值对中删除重复数据。这些重复具有完全相同的键,或者键可以彼此非常接近。在那种情况下,我只想保留最大的键值对。

this answer

中提供的解决方案
ind=-1;
while(~isempty(ind))
  %find the non-max point
  Max=([diff(vals) 0]<0 & [0 -diff(vals)]<0); 
  Nind=1:length(vals);
  Nind(Max)=[];

  %determine the range of points
  Cind=[0 diff(keys)<0.5 & abs(diff(keys)>0.01)];
  Cind(find(Cind)-1)=1;
  vec=1:length(Cind);
  Cind=Cind.*vec;
  Cind(Cind == 0)=[];

  %check through & back
  ind=intersect(Cind,Nind);
  keys(ind)=[];
  vals(ind)=[];
end

适用于给定的一对配对

keys = [1 2 3 3.1 3.15 4 5];
vals = [0.8 1 1.1 1.3 1.2 1 1.1];

所以当输入看起来像

Input plot

然后输出看起来像这样

enter image description here

删除36周围的重复。

但是,如果我对集合应用相同的解决方案

keys = [414 414 999 1011 1070 1280 1280 1635 1641 1793 1799 1870 1872 1886 2213 2214 2225 2572 3778 3790 4970];
values = [1.100 1.100 0.316 0.198 0.224 0.555 0.555 0.443 0.374 0.387 0.510 0.446 0.456 0.347 0.224 0.229 0.171 0.175 0.202 0.183 0.147];

并相应地将阈值更改为

Cind=[0 diff(keys)<13 & abs(diff(keys)>0.01)];

然后输入看起来像

input plot 2

输出看起来像

output plot 2

在这种情况下,问题是删除了太多点。例如,在红色圆圈中,该组中的最大点被删除,并且该区域中的三个点中,尽管距离远高于设置的阈值13,但仅保留了一个点。尽管所有较大的值都被删除,但在1635中的点也被删除了再走13点。

我在这里误会什么?

编辑:期望的输出将是那些键值对非常接近的那些键值对,只有一对最大的键将被保留,而另一个键将被从两者中删除。数组。我指出了应该合并到该图中最大值的那些点:

Indication of desired output

编辑2:因此,所需的输出数组将是:

keys = [414 999 1070 1280 1635 1799 1872 1886 2213 2225 2572 3778 4970];
vals = [1.100 0.316 0.224 0.555 0.443 0.510 0.456 0.347 0.224 0.171 0.175 0.202 0.147];

2 个答案:

答案 0 :(得分:1)

似乎该代码将删除两个相邻的点,其中一个接近一个较大的值,第二个点与第一个被删除的点接近,但不会保留较大的值。最简单的解决方法(不是最漂亮的解决方法)是在循环的每次迭代中仅删除一个元素。例如:

while true         % changed code
  %find the non-max point
  Max=([diff(vals) 0]<0 & [0 -diff(vals)]<0); 
  Nind=1:length(vals);
  Nind(Max)=[];

  %determine the range of points
  Cind=[0 diff(keys)<13 & abs(diff(keys)>0.01)];
  Cind(find(Cind)-1)=1;
  vec=1:length(Cind);
  Cind=Cind.*vec;
  Cind(Cind == 0)=[];

  %check through & back
  ind=intersect(Cind,Nind);
  if isempty(ind)  % added code
     break         % added code
  end              % added code
  ind=ind(1);      % added code
  keys(ind)=[];
  vals(ind)=[];
end

PS:为什么将& abs(diff(keys)>0.01)添加到上一个答案?它会导致保留非常接近的要点,这与您对问题的描述不同,这不是您的意图。

答案 1 :(得分:1)

这是一种直接,非常简单的策略,它仅包含一些if语句并一次删除一个点,但是仍然有效。

但是,以下代码的复杂度为 O(N ^ 2),与向量化无关,当输入变得可观时,这将非常耗时。

%% Input
clc; clear;
keys = [414 414 999 1011 1070 1280 1280 1635 1641 1793 1799 1870 1872 1886 2213 2214 2225 2572 3778 3790 4970];
vals = [1.100 1.100 0.316 0.198 0.224 0.555 0.555 0.443 0.374 0.387 0.510 0.446 0.456 0.347 0.224 0.229 0.171 0.175 0.202 0.183 0.147];

%% Dealing
[len,flag]=deal(13,1);
while flag
  flag=0;
  for ii=2:length(keys)
    if ((keys(ii)-keys(ii-1) > len))
      continue;
    else
      if (vals(ii) > vals(ii-1))
        keys(ii-1)=[];
        vals(ii-1)=[];
      else
        keys(ii)=[];
        vals(ii)=[];
      end
      flag=1;
      break;
    end
  end
end

%% plot
figure(1)
plot(keys,vals)
hold on 
plot(keys,vals,'ro')
for ii=1:length(vals)
  text(keys(ii),vals(ii),num2str(ii))  
end

代码将输出:

enter image description here