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

 采纳的回答

Andrei Bobrov
Andrei Bobrov 2019-5-14
编辑:Andrei Bobrov 2019-5-15
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 个评论

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.
It works!!!Thank you very much!!!!!!

请先登录,再进行评论。

更多回答(2 个)

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 个评论

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?

请先登录,再进行评论。

Jan
Jan 2019-5-16
编辑:Jan 2019-5-16
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 个评论

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.
@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? ...

请先登录,再进行评论。

类别

帮助中心File Exchange 中查找有关 Creating and Concatenating Matrices 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by