normalize all but the zeros in a vector?

I have a vector that contains 0s, something like this [44 0 23 19 0 0 30]
and I want to normalize the non-0 elements to 1-10, for instance, but the 0s keep messing it up.
Is there a way (hopefully without using loops) to normalize while not affecting the 0s? In other words, take the values from 19-44 and convert them to stretch over 1-10.

 Accepted Answer

%Input
in = [44 0 23 19 0 0 30];
%Lazy preallocation, assuming all values are finite and not NaNs
out = 0*in;
%Indexing for non-zeros values
idx = in~=0;
%Output
out(idx) = rescale(in(idx), 1, 10)
out = 1×7
10.0000 0 2.4400 1.0000 0 0 4.9600

6 Comments

Works like a charm, thank you so much!!!
Not complaining, but the "lazy preallocation" can potentially, rarely, produce artifacts that might lead to some debugging time. Suppose the vector contains some inf elements? Then a multiplication by zero will produce NaNs.
x = [1 2 3 4 inf 5 6];
y = 0*x
y = 1×7
0 0 0 0 NaN 0 0
So if you were expecting all zero elements in there, because you multiplied by zero, then you would be surprised. A minor point, really.
You are right, @John D'Errico, and the reason you have mentioned is why I use the phrase "lazy preallocation".
Since I have worked mostly with finite and non-NaN (that felt weird to write) values, it has became kind of ingrained in me to use that method.
I have edited my comment to incorporate assumptions made to use it accordingly.
Honestly, will the problem I mentioned ever come up? Probably not often. But as soon as I say that, it will happen. Anyway, my ingrained habit is to use
y = zeros(size(x));
which is not much harder to write than 0*x. It is surely faster to execute, but the difference will be literally immeasurable unless the array is pretty large.
x = rand(10000);
timeit(@() 0*x)
ans = 0.1748
timeit(@() zeros(size(x)))
ans = 7.4274e-06
"But as soon as I say that, it will happen."
Haha, yes.
Mine used to be that too, but I am not sure how it changed into multiplying with 0. I think I'll go back to using zeros() soon, specially noting the difference in speed.
However, keeping performance in mind, maybe I should revisit this thread - https://in.mathworks.com/matlabcentral/answers/51411-initialize-a-mxn-matrix-with-the-same-number#answer_453549
y = zeros(size(x), 'like', x);
for extra robustness.

Sign in to comment.

More Answers (0)

Categories

Find more on Mathematics in Help Center and File Exchange

Products

Release

R2022a

Tags

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!