Replace percentage of existing values with new value

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

 Respuesta aceptada

Richard Zapor
Richard Zapor el 20 de Nov. de 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 comentario

Michael
Michael el 20 de Nov. de 2012
Richard,
Thanks this works and I was able to adapt it to the matrices (described above) that I will be using.
Cheers,
Michael

Iniciar sesión para comentar.

Más respuestas (2)

Matt Fig
Matt Fig el 19 de Nov. de 2012
B(randperm(16,4)) = 5

5 comentarios

Michael
Michael el 20 de Nov. de 2012
Matt, Thanks for the quick response. I tried the code you suggested, but it produces a new matrix, C, where 4 of the elements of B have been randomly replaced by the value 5. I was asking if there was a method to replace a given percentage of each extant value in A. The above code, as far as I can tell, replaces 25% of the elements of A, not 25% of each extant value. Please advise.
Thank you,
Mike
Matt Fig
Matt Fig el 20 de Nov. de 2012
I see, your use of the word 'extant' (existing) rather than 'unique' is what threw me. I'll post an update when I get nack to MATLAB.
Matt Fig
Matt Fig el 20 de Nov. de 2012
Editada: Matt Fig el 20 de Nov. de 2012
Further questions: Are your matrices all made of such a nice pattern as the example matrix (row of 1s, row of 2s, etc.) or are they more like:
B = randi(5,5,5)
In either case, what if there are a number of, say, 1s that is not evenly divisible by 4? Say there are three 1s, how many to replace? What if there is only one 1?
For the particular example you give, this would work:
idx = (1:4) + (randi(4,1,4)-1)*4;
B(idx) = 5
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 el 20 de Nov. de 2012
Editada: Matt Fig el 20 de Nov. de 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

Iniciar sesión para comentar.

Image Analyst
Image Analyst el 20 de Nov. de 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 comentario

Michael
Michael el 20 de Nov. de 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

Iniciar sesión para comentar.

Productos

Preguntada:

el 19 de Nov. de 2012

Community Treasure Hunt

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

Start Hunting!

Translated by