查找Matlab中的每一行是否重复

use*_*148 3 matlab

A在维度的Matlab中有一个矩阵MXN.我想创建一个B维度向量,Mx1其中B(i)=1if A(i,:)不会多次重复A,0否则.

例如

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

B=[0;1;0;1];
Run Code Online (Sandbox Code Playgroud)

这段代码

[vu,vx,vx]=unique(A,'rows');
n=accumarray(vx,1);
C=[vu n]
Run Code Online (Sandbox Code Playgroud)

有助于找到每行的出现次数.因此,通过添加一个循环,我应该能够C得到B所需的.但是,在我的实际情况下M非常大(80000).我能用得更快吗?

Sue*_*ver 10

与您的代码的问题是,第二输出unique只返回第一次出现的每个唯一值的和第三输出返回索引数组成对应于输入的第一输出.这些都不能直接得到你想要的东西.如果将它们组合在一起,就可以得到你想要的东西

[~, a, b] = unique(A, 'rows');
B = accumarray(a(b), 1, [size(A, 1), 1]) == 1;
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用ismember带有该'rows'选项的第二个输出来查找共享行的索引.然后,您可以使用它accumarray来确定重复行的次数并将结果与​​之比较1

[~, bi] = ismember(A, A, 'rows');
B = accumarray(bi, 1, [size(A, 1), 1]) == 1;
Run Code Online (Sandbox Code Playgroud)

在简单的基准测试中,使用选项unique往往会产生最佳结果

function comparison()

    nRows = round(linspace(100, 100000, 30));

    times1 = nan(size(nRows));
    times2 = nan(size(nRows));

    for k = 1:numel(nRows)
        A = randi(10, nRows(k), 4);
        times1(k) = timeit(@()option1(A));
        times2(k) = timeit(@()option2(A));
    end

    figure
    p(1) = plot(nRows, times1 * 1000, 'DisplayName', 'unique');
    hold on
    p(2) = plot(nRows, times2 * 1000, 'DisplayName', 'ismember');
    ylabel('Execution time (ms)')
    xlabel('Rows in A')
    legend(p)
end


function B = option1(A)
    [~, a, b] = unique(A, 'rows');
    B = accumarray(a(b), 1, [size(A, 1), 1]) == 1;
end

function B = option2(A)
    [~, bi] = ismember(A, A, 'rows');
    B = accumarray(bi, 1, [size(A, 1), 1]) == 1;
end
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述