代码之家  ›  专栏  ›  技术社区  ›  Axel

删除重复会删除太多的点

  •  0
  • Axel  · 技术社区  · 6 年前

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

    提供的解决方案 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

    去掉周围的重复 3 6 是的。

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

    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 回复  |  直到 6 年前
        1
  •  1
  •   Hunter Jiang    6 年前

    这里有一个简单明了的策略,它只包含一些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

        2
  •  1
  •   Cris Luengo    6 年前

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

    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) 对上一个答案?它导致非常接近的点被保留,这不是你的意图是根据你的问题描述。