我有一个大矩阵(500212x7)和一个像下面的列向量
matrix F vector P
0001011 4
0001101 3
1101100 6
0000110 1
1110000 7
向量包含在矩阵行内考虑的索引。 P(1)指向F(1,4),P(2)指向F(2,3),依此类推。
我想否定P元素所指向的列中F的每一行中的某一位(在同一行中)。
我想到了类似的东西
F(:,P(1)) = ~F(:,P(1));
F(:,P(:)) = ~F(:,P(:));
但是这些情况当然不会产生我期望的结果,因为第一行不会更改P元素,第二行甚至不会让我启动程序,因为完整的向量无法建立索引。 / p>
我的想法是我需要对所有F和P行(“同时”更改/递增)执行此操作,但要采用P元素的值。
我知道这很容易通过 for 循环实现,但是由于F数组的尺寸很大,因此解决该问题的方法是完全不可接受的。
是否有任何一种Matlab向导可以通过使用矩阵运算来解决此类任务?
答案 0 :(得分:4)
我知道使用for循环很容易实现这一点,但是由于F数组的尺寸很大,因此解决问题的方法是完全不可接受的。
您永远不要做出这样的假设。首先实现循环,然后检查它是否真的对您来说太慢,然后担心优化。
在这里,我正在比较Luis' answer和trival循环:
N = 500212;
F = rand(N,7) > 0.6;
P = randi(7,N,1);
timeit(@()method1(F,P))
timeit(@()method2(F,P))
function F = method1(F,P)
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries
end
function F = method2(F,P)
for ii = 1:numel(P)
F(ii,P(ii)) = ~F(ii,P(ii));
end
end
Luis的答案的时间为0.0065 s,循环的时间为0.0023 s(MATLAB在线R2019a)。
对于非常大的数组,尤其是是正确的,如果矢量化需要创建中间数组,则循环比矢量化代码要快。内存访问很昂贵,使用更多内存会使代码变慢。
经验教训:不要忽略循环,不要过早尝试优化,也不要在没有比较的情况下进行优化。
答案 1 :(得分:3)
另一种解决方案:
xor( F, 1:7 == P )
说明:
1:7 == P
生成一个热阵列。xor
将使位保留其值,以0表示,并将其翻转为1。答案 2 :(得分:2)
不确定它是否符合 wizardry 的要求,但是linear indexing确实可以满足您的要求:
F = [0 0 0 1 0 1 1; 0 0 0 1 1 0 1; 1 1 0 1 1 0 0; 0 0 0 0 1 1 0; 1 1 1 0 0 0 0];
P = [4; 3; 6; 1; 7];
ind = (1:size(F,1)) + (P(:).'-1)*size(F,1); % create linear index
F(ind) = ~F(ind); % negate those entries