Select random data from a matrix and replace it

Hello,
I have the following problem: I have a matrix e.g
1 0 1 0 1
1 1 1 0 0
1 1 1 1 1
1 1 0 0 1
and I try to do this: When the sum of each column exceeds the threshold=4 some random "1" of the column that goes beyond the threshold become zero. How do I implement this in matlabThis can be done without using loops?I would be very grateful if someone helpend me

 Réponse acceptée

Andrei Bobrov
Andrei Bobrov le 14 Mai 2019
Modifié(e) : Andrei Bobrov le 15 Mai 2019

0 votes

A = [1 0 1 0 1
1 1 1 0 0
0 0 0 0 0
1 1 1 1 1
1 1 0 0 1
0 0 0 0 0];
p = 4;
[ii,jj] = find(A);
jjj = accumarray(ii,jj,[size(A,1),1],@(x){x(randperm(numel(x),min(numel(x),p)))});
k = cellfun(@numel,jjj);
out = accumarray([repelem((1:numel(k))',k),cell2mat(jjj)],1,size(A));

5 commentaires

Stelios's "Answer" moved here:
I tried what you have told me. I tried in a matrix 840X1145 (that is matrix A has dimensions of 840X1145) and the resulting out matrix has dimensions of 840X1140. Why is that? Also, I will use the matrix out in other calculations, but Matlab errors out due to dimension mismatch. How does this solution work?
Please attach your matrix "A" in a .mat file with the paper clip icon.
The matrix A that I mention is a matrix 840X1145 and contains "1" and "0" and I tested the above solution the new matrix resulting i.e the matrix out has dimensions 840X1140. How to solve this problem because the matrix out it should also have dimensions of 840X1145 so I can make some other calculations.
I'm fixed.
It works!!!Thank you very much!!!!!!

Connectez-vous pour commenter.

Plus de réponses (2)

Jos (10584)
Jos (10584) le 15 Mai 2019
Modifié(e) : Jos (10584) le 15 Mai 2019
Here is another, indexing, approach:
A = randi(2, 6, 8)-1 % random 0/1 array
M = 3 % max number of 1's per column
szA = size(A) ;
B = zeros(szA) ;
tf = A == 0 ;
[~, P] = sort(rand(szA)) ; % randperm for matrix along columns
P(tf) = 0 ;
[~, r] = maxk(P, M) ; % rows with M highest values in P (including 0's) per column
i = r + szA(1)*(0:szA(2)-1) ; % convert to linear indices
B(i) = 1 ; % B contains M 1's per column
B(tf) = 0 % reset those that were 0 in A -> only maximally M 1's per column remain

2 commentaires

Works what I suggest and thank you very much!!!
I just have the following question: Once matrix B is created with
0 's and 1 's how it stays stable without changing put 0 's and 1's every time i run the code?
I don't get it. Why not simply run the code only once for a given matrix A?

Connectez-vous pour commenter.

Jan
Jan le 16 Mai 2019
Modifié(e) : Jan le 16 Mai 2019
A logical mask is much simpler than handling the indices:
A = randi([0,1], 8, 8); % Test data
p = 4;
mask = (cumsum(A, 1) > p) & A;
A(mask) = randi([0,1], nnz(mask), 1);
This replaces 1s in each column by a 0 with a probability of 50%, but leaves the first p ones untouched.
But if you want to change any 1s without keeping the first p 1s of each column:
mask = (sum(A, 1) > p) & A; % cumsum -> sum, auto-expand: >= R2016b
A(mask) = randi([0,1], nnz(mask), 1);
If you want to replace the 1s in the columns with more than p 1s with another probability:
A(mask) = rand(nnz(mask), 1) > 0.85;

3 commentaires

I assumed that the OP wanted to leave a maximum number (M) of ones in each column. If there are more than M ones in a column, a random selection of those should be set to 0, so M ones remain.
Jan
Jan le 16 Mai 2019
Modifié(e) : Jan le 16 Mai 2019
@Jos: A maximum number of ones? Do you mean a minimum number of ones? I admit, I'm more and more confused.
From the OP: "When the sum of each column exceeds the threshold=4 some random "1" of the column that goes beyond the threshold become zero."
If I now read it again, just a single one in such a column should be set to 0 then? ...

Connectez-vous pour commenter.

Catégories

Tags

Community Treasure Hunt

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

Start Hunting!

Translated by