我正在寻找另一种替代方案" X = X1(abs(N(4,:) - N(5,:))> 0.24 * abs(N(5,:)))"

时间:2015-07-10 22:51:49

标签: matlab matrix

此问题的目标:

我正在寻找一个不考虑矩阵NM的列顺序的代码。所以我尝试在下面的代码中替换以下行:

X = X1(abs(N(4,:)-N(5,:))>0.24*abs(N(5,:)));

结果X取决于NM

的列顺序

问题:

如果M(4,:)

,我的目标是将N(1:3,i), i=1,2,3,4,5对应X的所有值放在单元格abs(N(4,i)-N(5,i)) > 0.24*abs(N(5,i))的一个向量中

N(1:3,:)M(1:3,:)

的唯一列向量组成

N(4:5,:)用于查找X

添加实体A以显示M

M = [1007  4044  1007  4044  1007  5002 5002 5002 622 622  1007  1007  1007;
      552   300   552   300   552   431  431  431 124 124   552    11    11; 
     2010  1113  2010  1113  2010  1100 1100 1100  88  88  2010    20    20;
       12    25    15    12    30     2   10   55  32  12     7    12     7];


A = [1007  4044  5002  622  1007
      552   300   431  124    11
     2010  1113  1100   88    20
       12    25     2   32    12
       15    12    10   12     7
       30          55
        7                        ]

N =  [622  1007 1007  4044  5002;
      124    11  552   300   431;
       88    20 2010  1113  1100;
        2     4 -1.1   2.1    -3;
     2.01     1   -1     2    -5];

[~,~,idx] = unique(M(1:3,:)','rows','stable')


%// Accumulate elements from the fourth row of M based on the IDs
X1 = accumarray(idx(:),M(4,:).',[],@(x) {x});   

%// Use mask corresponding to abs(N(4,i)-N(5,i))>0.24*N(5,i) and
%// filter out some of the cells from the output
X = X1(abs(N(4,:)-N(5,:))>0.24*abs(N(5,:)));

我的例子: 如果NM正确排序:

X = {[12,7],[2 10 55]}

[12 7]对应N(1:3,2)abs(N(4,2)-N(5,2))>0.24*abs(N(5,2))

[2 10 55]对应N(1:3,5)abs(N(4,5)-N(5,5))>0.24*abs(N(5,5))

可能的解决方案:(使用我的真实数据提供正确的结果)

for i = 1:size(N,2)
    N(6,i) = i;
end


for h = 1:size(M,2)
    for l = 1:size(N,2)
        if M(1:3,h) == N(1:3,l) 
           M(5,h) = N(6,l);
        end
    end
end

p = 0;  
for i = 1:size(N,2)
    if abs(N(4,i)-N(5,i))>0.24*abs(N(5,i))
       Mint = M(:,ismember(M(5,:).',i.', 'rows').'); 
       p = p+1;
       X{1,p} = Mint(4,:);
    end
end

3 个答案:

答案 0 :(得分:1)

看看这是否适合你 -

%// Inputs
M = [1007  4044  1007  4044  1007  5002 5002 5002 622 622  1007  1007  1007;
      552   300   552   300   552   431  431  431 124 124   552    11    11; 
     2010  1113  2010  1113  2010  1100 1100 1100  88  88  2010    20    20;
       12    25    15    12    30     2   10   55  32  12     7    12     7];

N =  [622  1077 1007  4044  5002;
      124    11  552   300   431;
       88    20 2010  1113  1100;
        2     4 -1.1   2.1    -3;
     2.01     1   -1     2    -5];

[unqrows,~,idx] = unique(M(1:3,:)','rows','stable')
unqcols = unqrows.';

%// Accumulate elements from the fourth row of M based on the IDs
X1 = accumarray(idx(:),M(4,:).',[],@(x) {x});  %//'

%// "Regularize" X1  %//'
[~,sort_idx] = sortrows(unqcols.');  %//'
X1_sorted = X1(sort_idx);

%// Use mask corresponding to abs(N(4,i)-N(5,i))>0.24*N(5,i) and
%// filter out some of the cells from the output
X = X1_sorted(abs(N(4,:)-N(5,:))>0.24*abs(N(5,:)));

%// Sort, keep unique elements and make them row vectors 
%// within each cell of X (if needed)
X = cellfun(@(x) unique(x).',X,'Uni',0);

输出 -

>> celldisp(X)
X{1} =
     7    12
X{2} =
     2    10    55

答案 1 :(得分:1)

使用逻辑索引可以显着加快脚本速度。 MATLAB在for循环方面表现不佳。请尝试以下代码:

k = size(N,2);
r = size(M,2);
M(5:7,:) = 0;

for ii = 1:k
    index = sum(M(1:3,:) == repmat(N(1:3,ii),1,r),1)>2;
    M(5,index) = ii;
    M(6,index) = N(4,ii);
    M(7,index) = N(5,ii);
end

filter = abs(M(6,:)-M(7,:))>0.24*abs(M(7,:));

X = {};
for ii = 1:k
    X = [X, M(4,M(5,:) == ii& filter)];
end

在我的计算机上,执行代码需要0.017825秒。我花了0.002780秒。我会说这有一些改进。如果您想进行更详细的比较,请使用profile

答案 2 :(得分:1)

ismember是解决问题的好方法。它告诉您一个矩阵的元素(或行)何时出现在第二个矩阵中,并且比使用循环的方法快得多。此代码与您发布的较大数据集上的解决方案相匹配:

isGood = abs(N(4,:)-N(5,:))>0.24*abs(N(5,:));

[junk, inds] = ismember(M(1:3, :)', N(1:3, isGood)', 'rows');

X = cell(1, sum(isGood));
for i = 1:sum(isGood)
    X{i} = M(4, inds==i);
end