Replace percentage of existing values with new value

3 views (last 30 days)
Hello, I'd like to replace a percentage of each existing value in a matrix or vector with another value? For example, I have matrix B which has values 1, 2, 3, and 4 and I want to replace 25% of each of these extant values with '5,' is there a sweet way to do this? The result would be matrix C, that is, 25% would mean one element of each extant value changed to / replaced with '5'. I'm afraid I am not sure where to start.
B = [1 1 1 1;
2 2 2 2;
3 3 3 3;
4 4 4 4];
C = [1 1 1 5;
2 2 5 2;
3 5 3 3;
4 4 5 4];
Thank you,
Mike

Accepted Answer

Richard Zapor
Richard Zapor on 20 Nov 2012
function replace25
m = randi(4, 9, 9)
newvalue = 5;
% determine qty of values 1 thru 4, a(1) qty 1, a(4) number 4s
a=hist(m(:),4)
for i=1:4
% find first 25 % of a value and give it new value
m(find(m==i,round(a(i)/4)))=newvalue;
end
m
end
  1 Comment
Michael
Michael on 20 Nov 2012
Richard,
Thanks this works and I was able to adapt it to the matrices (described above) that I will be using.
Cheers,
Michael

Sign in to comment.

More Answers (2)

Matt Fig
Matt Fig on 19 Nov 2012
B(randperm(16,4)) = 5
  5 Comments
Michael
Michael on 20 Nov 2012
Matt, I agree, unique is better than extant for this arena, thanks for bringing that to my attention.
All of the matrices I will be using will have 5 initial unique values. They will all be ordered similarly to the above. However, as in the example below, sometimes there will be more than 1 row per unique value. As far as the divisibility issue, I'd say round up to the next integer. I think I understand how the code works that you posted most recently, thanks.
Thanks again,
Mike
mat = zeros(10,10);
[M N] = size(mat);
vals = [0 1 2 3 4]; % 5 initial unique values
vL = numel(mat);
nVals = length(vals);
idx = floor(linspace(1,nVals+1-2*eps(nVals),vL));
out_vec = vals(idx);
out_mat = vec2mat(out_vec,M); % orderly unique values, aggregated by row
Matt Fig
Matt Fig on 20 Nov 2012
Edited: Matt Fig on 20 Nov 2012
O.k. Here is a more generalized code:
N = 4; % This controls the code: a positive integer.
vals = 0:N;
nVals = N + 1;
M = nVals*randi(4); % Up to size nVals*4
idx = floor(linspace(1,nVals+1-2*eps(nVals),M^2));
out_vec = vals(idx);
% orderly unique values, aggregated by row:
out_mat = vec2mat(out_vec,M)
% Now, we have nVals unique values in out_mat.
% So we want 1/4 of the set of each of
% those (M*N) values set to another value,
% say -1 for example....
CV = -1; % The change value, set as needed...
PE = floor(M^2/nVals/4); % 1/4 of the number of each
for ii = 0:M/nVals:M-1
cnt = 0;
while cnt<PE
R = randi(M/nVals) + ii;
C = randi(M);
if out_mat(R,C)~=CV
out_mat(R,C) = CV;
cnt = cnt + 1;
end
end
end
out_mat

Sign in to comment.


Image Analyst
Image Analyst on 20 Nov 2012
Michael, I think this code does what you want in a pretty flexible and robust way:
m = int32(randi(4, 9, 9))
replacementValue = 5;
% Get the unique values in m
uniqueValues = unique(m)
% Make a new output array so that the replacement value
% can be one of the input values. This allows
% maximum flexibility and robustness.
% For example what if the replacment value = 3
% without having a copy you'd replace values already replaced.
mOut = m;
for k = 1 : length(uniqueValues)
thisValue = uniqueValues(k)
% Count the number originally at this value.
count = sum(m(:) == thisValue)
% Get the number to replace, rouding up.
numberToReplace = int32(ceil(0.25 * count))
% Pick them from random locations
linearIndexes = randperm(numel(m));
indexesToReplace = linearIndexes(1:numberToReplace);
% Do the assignments.
mOut(indexesToReplace) = replacementValue;
end
% Do the replacements
m = mOut;
% Display final m.
m
  1 Comment
Michael
Michael on 20 Nov 2012
Image Analyst,
Thank you for the reply. I didn't know about the unique command, thanks. If, for example, I replace the m in your code, with B above -- I have the same issue as I did with the first code suggested by Matt above. That is, whilst your code is much more adaptable, it still is replacing 25% of the entire matrix, and not 25% of each value. Is is it possible to replace x% of each unique value?
Thank you,
Mike

Sign in to comment.

Products

Community Treasure Hunt

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

Start Hunting!