矩阵行的中点取决于Matlab的某些条件

时间:2013-08-02 15:48:54

标签: matlab

我有一个尺寸为10x100的矩阵A,如下所示。我想做的是:

  1. 我将逐行工作,每行我会查看数据 这一行中的每个coloumn
  2. 假设我现在位于第一行的第一个col单元格中。我将检查值是否为零我将移动到下一个col,依此类推,直到我发现col具有非零值并保存其col号,例如col 3“这意味着col 1& 2是零”
  3. 现在我在第一行中的第一个非零col,我将移动到下一个col,直到找到一个零值的col。我将在此零之前获取col,它必须是非零的并保存它。例如col 7“这意味着col4& 5& 6是非零且col8为零”
  4. 现在我想保存这两列之间的中间色列,例如col3和col7,然后中间col是col5,所以我将保存索引row1_col5。如果有两个中间值,那么它们中的任何一个都没问题。
  5. 然后我会移动到下一个col,直到我找到一个非零的col“做 相同的步骤从2 - > 5“直到第一行结束。
  6. 移至下一行并从第2步 - > 5开始重新开始。
  7. 有两个规则: - 第一个是,如果有至少3个非零连续值,如果有两个非零连续值,我将得到非零连续值的中间索引然后中间将不会被计算 - 第二个是如果零个连续值的数量小于3,那么它们将被忽略并且将被视为非零值。例如,在下面的例子中,第一行中间值是col5和col11。在第2行中,计算col5,而第3行中的cols不满足此条件,并且将在第4行中计算col6或col7。
  8. 完成所有行后想要一个包含所有中间索引位置的向量或数组,例如row1_col5 row1_col17 row2_col_10等等。
  9. 示例:

    A = [ 0 0 0 2 4 1 0 0 0 1 3 2;
          0 0 0 5 1 1 1 1 0 0 0 1;
          0 3 4 1 0 3 1 2 0 0 1 3;
          0 0 0 0 1 3 4 5 0 0 0 0];
    

    对于第一行,中间值为5和11,依此类推 所以,如果有人可以请求建议我怎么能用最少的处理来做到这一点,因为这可以使用循环完成但是如果有更有效的方法呢?如果需要澄清,请告诉我。

3 个答案:

答案 0 :(得分:3)

现在你已经澄清了你的问题(再次......)这里是一个解决方案(仍然使用for循环......)。它包括“规则7” - 不包括少于三个元素的运行;它还包括该规则的第二部分 - 少于三个零的运行不计为零。新代码如下所示:

A = [ 0 0 0 2 4 1 0 0 0 1 3 2;
      0 0 0 5 1 1 1 1 0 0 0 1;
      0 3 4 1 0 3 1 2 0 0 1 3;
      0 0 0 0 1 3 4 5 0 0 0 0];

 retVal = cell(1, size(A, 1));
 for ri = 1:size(A,1)
     temp = [1 0 0 0 A(ri,:) 0 0 0 1]; % pad ends with 3 zeros + 1
                                       % so that is always a "good run"
     isz = (temp == 0); % find zeros - pad "short runs of 0" with ones
     diffIsZ = diff(isz);
     f = find(diffIsZ == 1);     
     l = find(diffIsZ == -1);
     shortRun = find((l-f)<3); % these are the zeros that need eliminating

     for ii = 1:numel(shortRun)
         temp(f(shortRun(ii))+1:l(shortRun(ii))) = 1;
     end

     % now take the modified row:
     nz = (temp(4:end-3)~=0);
     dnz = diff(nz); % find first and last nonzero elements
     f = find(dnz==1); 
     l = find(dnz==-1);
     middleValue = floor((f + l)/2);
     rule7 = find((l - f) > 2);
     retVal{ri} = middleValue(rule7);
 end

您必须使用单元格数组作为返回值,因为您不知道每行将返回多少元素(根据您更新的要求)。

上面的代码返回以下单元格数组:

{[5 11], [6], [7], [7]}

我似乎仍然不理解你的“规则7”,因为你说“第3行中没有列满足这个条件”。但在我看来,一旦我们消除了短暂的零点,就可以了。除非我误解你想要如何处理一系列直接到达边缘的非零数字(我认为没问题 - 这就是为什么你将11作为第1行中的有效列返回的原因;那么为什么不呢?你为第3行返回7 ??)

答案 1 :(得分:1)

试试这个:

sizeA = size(A);
N = sizeA(1);
D = diff([zeros(1, N); (A.' ~= 0); zeros(1,N)]) ~= 0;
[a b] = find(D ~= 0);

c = reshape(a, 2, []);
midRow = floor(sum(c)/2);
midCol = b(1:2:length(b))

在此之后,midRow和midCol包含您的质心的索引(例如,midRow(1)= 1,midCol(1)= 4,用于上面给出的示例矩阵。

答案 2 :(得分:0)

如果您不介意使用for循环:

A = [ 0 0 1 1 1 0 1;
      0 0 0 0 0 0 0;
      0 1 1 1 1 0 0;
      0 1 1 1 0 1 1;
      0 0 0 0 1 0 0]; % data

sol = repmat(NaN,size(A,1),1);
for row = 1:size(A,1)
  [aux_row aux_col aux_val] = find(A(row,:));
  if ~isempty(aux_col)
    sol(row) = aux_col(1) + floor((find(diff([aux_col 0])~=1,1)-1)/2);
    % the final 0 is necessary in case the row of A ends with ones
    % you can use either "floor" or "ceil"
  end
end

disp(sol)

尝试一下,看看它是否符合您的要求。我希望代码清楚;如果没有,请告诉我