我试图弄清楚如何在 MATLAB 中删除矩阵的元素,如果它与任何其他元素相差 0.01。我应该使用矩阵的所有独特元素作为我正在创建的 ROC 曲线的阈值,但我需要一种方法来删除彼此相差 0.01 以内的值(因为我们假设它们是如果这是真的,基本上相等)。
帮助将不胜感激!
谢谢!
如果您只是尝试从向量中删除该容差内的相邻值,我将从以下内容开始:
roc = ...
tolerance = 0.1;
idx = [logical(1) diff(roc)>tolerance)];
rocReduced = roc(idx);
'rocReduced' 现在是一个向量,其中所有值在原始向量的容差范围内没有相邻值。
这种方法有两个明显的局限性:
我怀疑以上还不够。也就是说,我想不出任何简单的操作可以克服这些(和其他)限制,同时仍然使用向量化矩阵操作。
如果性能不是一个大问题,那么以下迭代算法可能适合您的应用程序:
roc = ...
tolerance = 0.1;
mask = true(size(roc)); % Start with all points
last = 1; % Always taking first point
for i=2:length(roc) % for all remaining points,
if(abs(roc(i)-roc(last))<tolerance) % If this point is within the tolerance of the last accepted point, remove it from the mask;
mask(i) = false;
else % Otherwise, keep it and mark the last kept
last = i;
end
end
rocReduced = roc(mask);
这可以处理多个连续的子公差间隔,而不必全部丢弃。它还处理非单调序列。
MATLAB 用户有时会回避迭代解决方案(相对于矢量化矩阵运算),但有时当蛮力性能满足您的需求时,寻找更优雅的解决方案是不值得的。
让矩阵中的所有元素形成一个图 G = (V,E),如果两个顶点 (u,v) 之间的差异小于 0.01,则它们之间存在一条边。现在,为这个图构造一个邻接矩阵并找到度数最大的元素。删除它并将其添加到列表中,然后从图表中删除它的邻居并重复直到没有任何元素。
代码:
%% Toy dataset
M = [1 1.005 2 ;2.005 2.009 3; 3.01 3.001 3.005];
M = M(:);
A = false(numel(M),numel(M));
for i=1:numel(M)
ind = abs(M-M(i))<=0.01;
A(i,ind) = 1;
end
C = [];
while any(A(:))
[val ind] = max(sum(A));
C(end+1) = M(ind);
A(A(ind,:),:) = 0;
end
这具有 O(n^2) 的运行时间,其中您的矩阵有 n 个元素。是的,它很慢。
根据您的描述,您希望如何处理一系列值(如评论中已经指出的那样)并不是很清楚,例如 0.0 0.05 0.1 0.15 ...以及从矩阵中删除元素的实际含义:设置它们归零,删除整列,删除整行?
对于向量,它可能看起来像(类似于 Adams 解决方案)
roc = ...
tolerance = 0.1;
% sort it first to get the similar values in a row
[rocSorted, sortIdx] = sort(roc);
% find the differing values and get their indices
idx = [logical(1); diff(rocSorted)>tolerance)];
sortIdxReduced = sortIdx(idx);
% select only the relevant parts from the original vector (revert sorting)
rocReduced = roc(sort(sortIdxReduced));
该代码未经测试,但应该可以正常工作。
在使用阈值或容差来保持足够接近的值之前,您可以使用 matlab 内置的 unique() 来减少运行。通常,matlab 会尝试加速其内置程序,因此请尝试使用尽可能多的内置程序。