【问题标题】:Remove all zeros rows and columns, and replace them back in same locations using MATLAB删除所有零行和列,并使用 MATLAB 将它们替换回相同的位置
【发布时间】:2019-09-17 10:07:10
【问题描述】:

我有矩阵 data 并用

删除所有零行和列
data( ~all(data,2), : ) = [];
data( :, all(~data,1) ) = [];

提取结果矩阵后,现在我想将那些全为零的行和列替换回相同的位置,即相同的行和相同的列。

我意识到我需要获取零行和零列索引来替换回来。我怎样才能完成这项任务?

【问题讨论】:

  • 你能解释一下为什么用它们的替代品简单地覆盖全零行/列不是更容易/更好吗?为什么需要完全删除这些行?
  • 实际上我有一个算法适用于没有全零行或列的矩阵。所以我首先删除它们并运行算法,然后我得到具有不同条目的相同大小的矩阵(我在这里不解释为相同大小)。但我需要放回原来的全零行和列。这个过程仍然适用于我的任务。

标签: matlab matrix


【解决方案1】:

我觉得将data 保持原样会更容易,只需取出所需的值,然后稍后替换它们:

data=[1 0 1;0 1 0; 1 0 1];

values = data(data~=0);
values = values + 1;
data(data~=0) = values

更新

第一部分用于取出每个非零值。如果它应该只留下整行或零列,并且如果它们在具有值的列或行中也取出零:

data=[1 0 1 0;0 0 0 0;1 0 1 1];

values = data(any(data,2),any(data,1));
values = values + 1;
data(any(data,2),any(data,1)) = values

不是data变了,右上角的0变成了1

【讨论】:

  • 非常简单的方法,但我会对非零元素使用更严格的标准。至少应该是(data~=0) 才能捕获负值。
  • @Finn,代码不错!我不想删除至少有一个零的行或列,而是删除全零的行和列。此外,我需要单独获取结果矩阵,然后将那些全零的行和列加回
  • 全零部分很简单,我更新了解决方案,但我不完全确定“结果矩阵”是什么意思。如果是没有零线的矩阵,就是在values
【解决方案2】:

例如解释见cmets:

A = rand(100,10);
% Make some rows zeros
A([1 2 10 80],:) = 0;

% make boolean array for your condition
bool_zeros = all(A == 0, 2);

% find indices corresponding to boolean array
ind_zeros = find(bool_zeros);
ind_non_zeros = find(~bool_zeros);

A_nozeros = A;
A_nozeros(bool_zeros,:) = [];

% your algortihm, e.g. division by itself, would not work for zeros
somefun = @(x) x./x;
A_output = somefun(A_nozeros);

% put zeros in again
A_output_with_zeros = A;
A_output_with_zeros(bool_non_zeros,:) = A_output

【讨论】:

  • 这也适用于我的任务,并且是一个有用的答案。 @rinkert 谢谢!
【解决方案3】:

由于您明确希望将已删除的全零行和列恢复到其原始位置,因此这里有一个解决方案正是这样做的。基本上,我存储全零行和列的行和列索引。然后,使用这些索引进行删除本身。之后,我恢复了与之前删除的一样多的全零行和列,并将它们放在原始数据的“末尾”。最后,我确定了正确的“置换向量”来重新排列所有行和列。 (也许,笔和纸对于遵循线性代数很有用。)

代码如下:

% Set up test data.
data = 10 * rand(5);
data(data < 8) = 0

% Save original data for later comparison.
dataOrig = data;

% Find row and column indices off all-zero rows/columns.
rowIdx = find(all(~data, 2)).'
colIdx = find(all(~data, 1))
nRows = numel(rowIdx);
nCols = numel(colIdx);

% Remove all-zero rows/columns.
data(rowIdx, :) = [];
data(:, colIdx) = []

%%% Here goes your own function only working on the "cleaned" data.
% data = yourFunction(data)

% Restore all-zero rows/columns "at the end".
[rows, cols] = size(data);
data = [data; zeros(nRows, cols)];
data = [data, zeros(rows+nRows, nCols)];

% Restore original row and column order.
[rows, cols] = size(data);
permRow([rowIdx, setdiff(1:rows, rowIdx)]) = [(rows-nRows+1):rows, 1:(rows-nRows)]
permCol([colIdx, setdiff(1:cols, colIdx)]) = [(cols-nCols+1):cols, 1:(cols-nCols)]
data = data(permRow, permCol)

% Comparison
all(dataOrig(:) == data(:))

还有,运行的输出:

data =
   0.0000   0.0000   8.9283   0.0000   8.6185
   0.0000   0.0000   0.0000   0.0000   0.0000
   0.0000   0.0000   0.0000   0.0000   0.0000
   0.0000   0.0000   0.0000   8.2942   0.0000
   0.0000   8.0730   0.0000   0.0000   8.6491

rowIdx =
   2   3

colIdx =  
   1

data =
   0.0000   8.9283   0.0000   8.6185
   0.0000   0.0000   8.2942   0.0000
   8.0730   0.0000   0.0000   8.6491

permRow =
   1   4   5   2   3

permCol =
   5   1   2   3   4

data =
   0.0000   0.0000   8.9283   0.0000   8.6185
   0.0000   0.0000   0.0000   0.0000   0.0000
   0.0000   0.0000   0.0000   0.0000   0.0000
   0.0000   0.0000   0.0000   8.2942   0.0000
   0.0000   8.0730   0.0000   0.0000   8.6491

ans = 
   1

希望有帮助!

【讨论】:

  • 这也适用于我的任务,并且是一个有用的答案。 @HansHirse 谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-12
  • 1970-01-01
  • 2022-07-24
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
相关资源
最近更新 更多