我有以下函数用于在矩阵中展开1的数量,如果存在全0或全1的行,则必须删除该特定行
function ReducedMatrix = ReduceMatrix(result) D1 = sum(result(:)); NumberOfOnes = floor(D1*0.3); NewMatrix = zeros(size(result)); NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1; ReducedMatrix = NewMatrix; while numel(ReducedMatrix)/numel(NewMatrix) > 0.2 IndexOfFullRows = find(all(ReducedMatrix)); if isempty(IndexOfFullRows) break end ReducedMatrix(:,IndexOfFullRows(1)) = []; end end功能和输出的输入如下
result = 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 ReducedMatrix = 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 row_sum = 3 2 3 2 1 4 2 2 0 3 col_sum = 3 4 4 1 0 0 3 2 2 3现在,如果存在row_sum / col_sum等于0或1的行或列,则必须删除相应的行。 例如。 Row-R4,R9和Col-C4,C5,C6具有row_sum和col_sum为1,0。 因此,必须从矩阵中添加R4,R9,C4,C5,C6 = 5行,因此我的简化矩阵的大小应为5x5。 请注意,不应删除列,而是删除具有0和1的列,而不是删除相应的行。 类似地,该函数必须运行具有相同约束的较大矩阵。 我尝试了上述功能但是我没有足够的技能来达到我想要的效果,非常感谢任何帮助
I have got the following function for spreading out the number of 1's in a matrix and if there are rows with all 0's or all 1's then that particular row has to be deleted
function ReducedMatrix = ReduceMatrix(result) D1 = sum(result(:)); NumberOfOnes = floor(D1*0.3); NewMatrix = zeros(size(result)); NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1; ReducedMatrix = NewMatrix; while numel(ReducedMatrix)/numel(NewMatrix) > 0.2 IndexOfFullRows = find(all(ReducedMatrix)); if isempty(IndexOfFullRows) break end ReducedMatrix(:,IndexOfFullRows(1)) = []; end endThe input of the function and output are as follows
result = 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 1 1 1 1 0 1 0 1 1 0 1 1 1 1 1 0 1 1 1 1 1 1 0 1 1 1 0 1 1 0 1 1 1 0 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 1 1 0 1 1 1 1 1 1 ReducedMatrix = 0 1 1 0 0 0 0 0 1 0 0 1 0 0 0 0 0 1 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 1 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 row_sum = 3 2 3 2 1 4 2 2 0 3 col_sum = 3 4 4 1 0 0 3 2 2 3Now if there exists a row or column with the row_sum/col_sum equal to either 0 or 1 then then the corresponding row has to be deleted. For Example. Row-R4,R9 and Col-C4,C5,C6 have row_sum and col_sum as either 1,0. So adding them up R4,R9,C4,C5,C6 = 5 rows have to be eliminated from the matrix so my reduced matrix should be of the size 5x5. Please note column should not be eliminated and instead of removing columns having 0 and 1, the corresponding rows can be removed. Similarly this function has to run for larger matrices with the same constraints. I tried doing the above function however i do not possess enough skills to achieve my desired results, Any help is much appreciated
最满意答案
我看到了许多潜在的问题和可能的代码简化。
首先,你构造原始矩阵的方式, NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1; 可能不会像你期望的那样表现。 randi不保证相同的索引不会在输出中多次出现,因此您的新矩阵可能比原始矩阵少。 要解决这个问题,请使用randperm对元素进行randperm :
ReducedMatrix = [ones(1, NumberOfOnes), zeros(1, numel(result) - NumberOfOnes)]; ReducedMatrix = ReducedMatrix(randperm(numel(ReducedMatrix))); ReducedMatrix = reshape(ReducedMatrix, size(result));其次,您不需要将新矩阵构造为NewMatrix ,然后将其重新分配给ReducedMatrix = NewMatrix; 。 只做ReducedMatrix = zeros(size(result)); 并跳过重新分配。 对于while循环条件,其中NewMatrix似乎是“使用过”,请记住numel(NewMatrix) == numel(result) 。
如果您不删除同类列,只删除行,则不需要循环来执行删除:
rowSum = sum(ReducedMatrix, 2); rowMask = (rowSum == size(ReducedMatrix, 2) | rowSum == 0); ReducedMatrix(rowMask, :) = [];删除行时,原始代码似乎交换行和列索引。 它也没有处理全零的情况。 如果要删除不超过30%的行,可以在删除之前执行以下操作:
rowMask = find(rowMask); % Convert to indices rowMask = rowMask(1:min(numel(rowMask), round(0.3 * size(ReducedMatrix, 2))));I see a number of potential problems and possible simplifications to your code.
For one thing, the way you construct the original matrix, NewMatrix(randi(numel(NewMatrix),1,NumberOfOnes)) = 1; may not behave the way you would expect. randi does not guarantee that the same index will not appear multiple times in the output, so your new matrix may have fewer ones than the original. To solve this, shuffle the elements using randperm:
ReducedMatrix = [ones(1, NumberOfOnes), zeros(1, numel(result) - NumberOfOnes)]; ReducedMatrix = ReducedMatrix(randperm(numel(ReducedMatrix))); ReducedMatrix = reshape(ReducedMatrix, size(result));Secondly, you do not need to construct the new matrix as NewMatrix and then reassign it with ReducedMatrix = NewMatrix;. Just do ReducedMatrix = zeros(size(result)); and skip the reassignment. For the while loop condition, where NewMatrix appears to be "used", remember that numel(NewMatrix) == numel(result).
If you are not removing homogeneous columns, only rows, you do not need a loop to do the removal:
rowSum = sum(ReducedMatrix, 2); rowMask = (rowSum == size(ReducedMatrix, 2) | rowSum == 0); ReducedMatrix(rowMask, :) = [];Your original code seems to swap the row and column indices when removing the rows. It also did not handle the case of all zeros. If you want to remove not more than 30% of rows, you can do something like this before the removal:
rowMask = find(rowMask); % Convert to indices rowMask = rowMask(1:min(numel(rowMask), round(0.3 * size(ReducedMatrix, 2))));更多推荐
发布评论