【问题标题】:Reducing the number of 1's in a matrix based on some condition in matlab根据matlab中的某些条件减少矩阵中1的数量
【发布时间】:2016-08-11 05:47:40
【问题描述】:

我从一个动态改变矩阵大小的过程中的一个实例得到以下结果矩阵。

result =

 1     1     0     0     1     0     0     0     1     0
 1     0     1     1     1     1     1     1     1     1
 0     1     1     1     1     0     1     1     1     1
 0     1     1     1     1     0     0     0     1     0
 1     1     1     1     0     1     1     1     1     1
 0     1     0     0     1     1     0     0     1     0
 0     1     1     0     1     0     1     0     1     0
 0     1     1     0     1     0     0     1     1     0
 1     1     1     1     1     1     1     1     0     1
 0     1     1     0     1     0     0     0     1     1

以下代码的输出如下所示

D1=sum(sum((result)))
D1 =

63

D1 指定矩阵中 1 的总数,我需要将 1 的总数减少到最多 D1 的 30%,即 63 个必须变成 17-19 个 1 左右。

这样做必须满足以下条件。

  1. 所有列/行都不应全为零或全为一。
  2. 如果一行全为 1/0,则可以将其删除,并且矩阵的最终大小不应小于初始矩阵的 20%

绝望地寻求帮助!

提前致谢。

编辑:百分比更改为 30

【问题讨论】:

  • 到目前为止你尝试过什么?删除需要是随机的还是可以按顺序遍历行?
  • 如果按顺序执行就好了。 - Skogsv
  • 删除行适合我的情况,但是减少的大小应该小于初始矩阵的 20%
  • 使用sum(result(:)) 而不是sum(sum...
  • 删除列怎么样?

标签: matlab networking matrix


【解决方案1】:

一种方法如下:

  1. 创建一个大小与result相同的零矩阵
  2. 生成小于矩阵中元素总数的随机整数
  3. 使用这些整数作为索引,将 1 分配到新矩阵中
  4. 检查是否有行中包含所有行,如果是,则将其删除

你还没有指定如何分配新矩阵中的那些,所以我在这里假设一个随机分配。

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

编辑:删除了基于评论的列检查并将其变成了一个函数。

编辑 II: 将百分比更改为保持 30%。

【讨论】:

  • 请注意,OP now 想要约 30% 的,并且 no 列/行只包含零(行可以删除,但列不能)...
  • 我没有足够的声誉来评论您的答案,但也许 OP 应该用这些新要求更新问题?我可以更改我的代码以反映更改,但就目前而言,我已经回答了这个问题..
  • 您完全正确,这是 OP 的责任。我的回答也照原样解决了这个问题:)
【解决方案2】:

这是我的解决方案。这个想法是不断生成随机矩阵,直到其中一个符合标准。

function out = q38888147(result)
if nargin < 1
  result = [
   1     1     0     0     1     0     0     0     1     0
   1     0     1     1     1     1     1     1     1     1
   0     1     1     1     1     0     1     1     1     1
   0     1     1     1     1     0     0     0     1     0
   1     1     1     1     0     1     1     1     1     1
   0     1     0     0     1     1     0     0     1     0
   0     1     1     0     1     0     1     0     1     0
   0     1     1     0     1     0     0     1     1     0
   1     1     1     1     1     1     1     1     0     1
   0     1     1     0     1     0     0     0     1     1 ];
end

ones_ind = find(result);
n_ones = numel(ones_ind);
num_ones_to_keep = round(n_ones/10);

while true
  out = false(size(result)); % or tmp = zeros('like', result);
  % Sparsify:
  perm = randperm(n_ones, num_ones_to_keep);
  out(perm) = true;
  % Cleanup rows/columns:
  out = reduceInvalidRowCol(out);
  % Validate:
  if all(size(out) >= ceil(size(result)*0.2))
    break; % If all's good, finish
  end
end

end

function out = reduceInvalidRowCol(in,removeRows,removeCols)
if nargin < 3
  removeCols = false;
end
if nargin < 2
  removeRows = true;
end

out = in;
%% Check for all zeros / ones:
% Columns:
if removeCols
  s = sum(out,1);
  out(:,~s | s == size(out,1)) = [];
end
% Rows:
if removeRows
  s = sum(out,2);
  out(~s | s == size(out,2),:) = [];
end
end

【讨论】:

  • 解决方案效果很好,但是我得到全为零的列,我该怎么做才能在这些列中随机获得更多的零
  • @CJs - 请不要在回答后更改您的问题,这不是 Stack Overflow 的工作方式。当然,您会得到全零的列,因为输入数组的大小是 10*10,而您只需要 6 个。您需要更好地定义什么是“更多的”。请注意,如果您添加更多,那么〜10%将不再满足......您必须决定什么对您更重要。
  • 很抱歉,我对stackoverflow很陌生,因为它可以清楚地看到。超过10%的可以增加到30%。没有零的列或行是最高优先级
  • 你需要做两件事:1)将num_ones_to_keep乘以3(在round之前或之后)将其增加到~30%; 2) 在% Validate: 条件内,添加一行,根据我在removeCols 附近的代码测试全零列(如果存在这种情况,请不要break)。这样,一个有效的矩阵将最终生成。
猜你喜欢
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
相关资源
最近更新 更多