1

我需要将第一列中的值近似为第二列中最接近的值(我知道需要一个阈值,它可能是 0.0090)并保存索引。我一直在使用以下内容:

[ms, ix] = sort(m(:));
[r, c] = ind2sub(size(m),ix); 
proximity_threshold = 0.0090; 
ind = (diff(ms)<proximity_threshold);  
ind(end+1)=0;
n=0;
nn=0;
while n<numel(ix) 
    n=n+1;
    nn=nn+1;
    if ind(n) & c(n)~=c(n+1)
        a(nn,c(n))=ms(n);
        a(nn,c(n+1))=ms(n+1);
        n=n+1;
    else
        a(nn,c(n))=ms(n);
    end
end

但我对这个实现不满意。它近似值,但它返回一个大小为 (900 x 2) 的矩阵,我想要一个与原始矩阵 (500x2) 大小相同的矩阵。

谢谢!

4

2 回答 2

3

首先,您可以跳过矩阵m。在这种情况下,这是解决问题的一种不太理想的方法。另外,去掉末尾的零x_t。它们不是必需的。如果您需要帮助修剪最后的零,请尝试以下操作:

x_t = x_t(1:find(x_t~=0,1,'last'));

现在,为了匹配。x_t您可以找到与以下元素最接近的匹配项x

B = bsxfun(@minus, x_t(:), x(:).'); %'
[idx,~] = find(bsxfun(@eq, abs(B), min(abs(B))));
y = x_t(idx);

x现在在中找到的近似值,在 中找到y相应的索引idx

解释


bsxfun(@minus, x, y);

这将采用列向量x并减去每个或行向量的元素y。例如,

>> x = [3 6 9 12].'; y = [1 2 3];
>> ans = bsxfun(@minus, x, y);

ans =

     2     1     0
     5     4     3
     8     7     6
    11    10     9

或者换句话说,正在发生的事情是:

答案=

 (3-1)   (3-2)   (3-3)
 (6-1)   (6-2)   (6-3)
 (9-1)   (9-2)   (9-3)
(12-1)  (12-2)  (12-3)

bsxfun(@eq, A, min(A));

这会找到A列最小值所在的矩阵列中的位置。它返回一个逻辑矩阵(一和零)。例如,

>> A = [ 1  2  3  4;
      3  3  6  5;
      2  2  0  7;
      5  1  8  5;
      4  5  2  6];

>> ans = bsxfun(@eq, A, min(A))

ans =

    1   0   0   1
    0   0   0   0
    0   0   1   0
    0   1   0   0
    0   0   0   0

[idx,~] = find(A);

find命令搜索矩阵的所有非零元素A。通常你会调用它[row, col] = find(A);来取回行和列,但由于我只对行感兴趣,我过去常常~告诉 Matlab 我不想保留列值。


y = x(idx);

这将创建一个新向量y,其中包含由x引用的元素idx。由于我已经找到了使误差最小化的索引,因此我使用它们来提取x这些索引处的值。


把它们放在一起:

在较高级别上,代码执行以下操作:

  • 该矩阵Bx(columns) 的每个值与x_t(rows) 的每个值进行比较
  • 对于 的每一列 ( x) B,找到x_t使误差最小的行 ( )。
  • 知道行,我们可以x_t直接使用行索引提取值。

    希望这可以帮助!

    更新

    我意识到,如果 的值与x的两个值之间的距离完全相同,x_t那么您最终会得到一个太长的向量,因为将选择多个答案。下面是解决问题的方法。

    B = bsxfun(@minus, x_t(:), x(:).'); %'
    [idx,col] = find(bsxfun(@eq, abs(B), min(abs(B))));
    idx(1 < sum(triu(bsxfun(@eq, col(:), col(:).')))) = []; %'
    y = x_t(idx);
    

    基本上,添加的行所做的是丢弃与给定列中的第一个匹配项不对应的任何索引值。

  • 于 2013-11-07T20:31:46.397 回答
    2

    尼斯皮奥的回答很好,但匹配比必要的复杂得多。该interp1函数可用于将值映射到查找表条目。

    根据 nispio 的方法修剪 x_t:

    x_t = x_t(1:find(x_t~=0,1,'last'));
    

    现在我们使用专为查表设计的功能。

    idx = interp1(x, 1:numel(x), x_t, 'nearest');
    

    最后,获取找到的值,与 nisio 相同:

    y = x(idx);
    
    于 2013-11-07T23:18:17.480 回答