我在维度A
的Matlab中有一个矩阵MXN
。我想创建一个维B
的向量Mx1
,其中B(i)=1
如果A(i,:)
从未在A
多次重复,0
则为A=[1 2 3;
4 5 6;
1 2 3;
7 8 9];
B=[0;1;0;1];
。
例如
[vu,vx,vx]=unique(A,'rows');
n=accumarray(vx,1);
C=[vu n]
此代码
C
有助于查找每行的出现次数。因此,通过添加一个循环,我应该能够B
根据需要获得M
。但是,在我的实际情况中,project.json
非常大(80000)。我能用得更快吗?
答案 0 :(得分:10)
您的代码的问题是unique
的第二个输出仅返回每个唯一值的第一次出现,第三个输出将索引数组返回到对应的第一个输出中对输入。这些都不能直接得到你想要的东西。如果你把它们组合起来,就可以得到你想要的东西
[~, a, b] = unique(A, 'rows');
B = accumarray(a(b), 1, [size(A, 1), 1]) == 1;
另一种方法是使用ismember
的第二个输出和'rows'
选项来查找共享行的索引。然后,您可以使用accumarray
确定重复行的次数,并将结果与1
进行比较
[~, bi] = ismember(A, A, 'rows');
B = accumarray(bi, 1, [size(A, 1), 1]) == 1;
在简单的基准测试中,使用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