Ответ Андерса хорош, но для очень больших матриц создание этой трехмерной матрицы может быть дорогостоящим.
Прежде всего, я бы предложил поместить матрицы в массив ячеек.Это значительно облегчает программное управление многими массивами.То есть вместо A
, B
и т. Д. Работа с C{1}
, C{2}
и т. Д .:
C = {A,B,C};
Для внесения этого изменения требуется практически нулевая стоимость.
Теперь, чтобы найти все элементы, в которых одна из матриц имеет значение NaN:
M = isnan(C{1});
for ii=2:numel(C)
M = M | isnan(C{ii});
end
Аналогичный цикл затем устанавливает соответствующие элементы в NaN:
for ii=1:numel(C)
C{ii}(M) = NaN,
end
Этот последний цикл может бытьзаменяется вызовом cellfun
, но мне нравятся явные циклы.
EDIT: Вот некоторые моменты времени.Это еще один пример того, что циклы в современной MATLAB работают быстрее, чем эквивалентный векторизованный код.В прежние времена код цикла был бы в 100 раз медленнее.
Это тестовый код:
function so(sz) % input argument is the size of the arrays
C3 = cell(1,3);
for ii=1:numel(C3)
C3{ii} = create(sz,0.05);
end
C20 = cell(1,20);
for ii=1:numel(C20)
C20{ii} = create(sz,0.01);
end
if(~isequal(method1(C3),method2(C3))), error('not equal!'), end
if(~isequal(method1(C20),method2(C20))), error('not equal!'), end
fprintf('method 1, 3 arrays: %f s\n',timeit(@()method1(C3)))
fprintf('method 2, 3 arrays: %f s\n',timeit(@()method2(C3)))
fprintf('method 1, 20 arrays: %f s\n',timeit(@()method1(C20)))
fprintf('method 2, 20 arrays: %f s\n',timeit(@()method2(C20)))
% method 1 is the vectorized code from Ander:
function mask = method1(C)
mask = sum(isnan(cat(3,C{:})),3)>0;
% method 2 is the loop code from this answer:
function mask = method2(C)
mask = isnan(C{1});
for ii=2:numel(C)
mask = mask | isnan(C{ii});
end
function mat = create(sz,p)
mat = rand(sz);
mat(mat<p) = nan;
Это результаты на моей машине (с R2017a):
>> so(500)
method 1, 3 arrays: 0.003215 s
method 2, 3 arrays: 0.000386 s
method 1, 20 arrays: 0.016503 s
method 2, 20 arrays: 0.001257 s
Цикл в 10 раз быстрее!Для небольших массивов я вижу гораздо меньшую разницу, но код цикла все еще в несколько раз быстрее, даже для массивов 5x5.