Elementwise ifs en matlab: ¿existen?
-
08-07-2019 - |
Pregunta
Digamos que tengo la siguiente instrucción if básica:
if (A ~= 0)
% do something like divide your favorite number by A
else
% do something like return NaN or infinity
end
El problema es que A no es un número simple sino un vector. Matlab devuelve verdadero si ningún elemento en A es 0. ¿Qué estoy buscando es un vectorizado? forma de ejecutar la declaración if anterior para cada elemento en A.
En realidad, simplemente quiero hacer esto lo más rápido posible.
Solución
B = zeros(size(A));
B(A~=0) = FAV./A(A~=0);
B(A==0) = NaN;
Otros consejos
Los ifs vectorizados no existen, pero hay algunas opciones. Si desea probar todos o algunos de los elementos verdaderos, use la función all o any.
Aquí hay un ejemplo de modificación condicional de valores de una matriz:
b = A ~= 0; % b is a boolean matrix pointing to nonzero indices
% (b could be derived from some other condition,
% like b = sin(A)>0
A(b) = f(A(b)) % do something with the indices that pass
A(~b) = g(A(~b)) % do something else with the indices that fail
En general, para realizar una operación en algunos elementos de una matriz y otra operación en los elementos restantes, una solución de una línea es:
Z = B .* X + ~B .* Y;
donde B es una matriz lógica. Como ejemplo,
Z = (A == 0) .* -1 + (A ~= 0) .* A;
copia A pero asigna -1 en todas partes que A es cero.
Sin embargo, debido a que la pregunta trata sobre infinito o NaNs, se puede hacer aún más sucintamente:
Z = FAV ./ A; % produces inf where A == 0
Z = (A ~= 0) .* FAV ./ A; % produces NaN where A == 0
¿Está buscando todos los elementos distintos de cero? Puedes hacerlo de varias maneras.
nonzero = find(A); % returns indicies to all non-zero elements of A
y = x./A(nonzero); % divides x by all non-zero elements of A
% y will be the same size as nonzero
O para una línea, puede usar un condicional en lugar de indicaciones
y = x./A(A~=0); % divides x by all non-zero elements of A
Lo que debe hacer es identificar los elementos sobre los que desea operar. Yo usaría ENCONTRAR. Almaceno los resultados en VI (Indicaciones válidas) y lo uso para completar la matriz.
clear
clc
den = [2 0 2; 0 2 0; -2 -2 -2]
num = ones(size(den));
frac = nan(size(den));
vi = (den ~=0)
frac(vi) = num(vi)./den(vi)
vi = (den == 0)
frac(vi) = nan %just for good measure...