在Matlab中使用列方向零填充将向量重塑为矩阵 [英] Reshape vector to matrix with column-wise zero padding in matlab

查看:101
本文介绍了在Matlab中使用列方向零填充将向量重塑为矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于输入矩阵

in = [1 1;
      1 2;
      1 3;
      1 4;
      2 5;
      2 6;
      2 7;
      3 8;
      3 9;
      3 10;
      3 11];

我想获取输出矩阵

out = [1 5 8;
       2 6 9;
       3 7 10;
       4 0 11];

意味着我想将第二个输入列重塑为一个输出矩阵,其中将与第一个输入列中一个值相对应的所有值都写入输出矩阵的一列中.

由于在第一输入列中每个值可以有不同数量的条目(此处"1"和"3"有4个值,而"2"只有3个值),因此正常的重塑功能不适用.我需要将所有列填充到最大行数.

您知道如何执行这种matlab式的操作吗?

第二个输入列只能包含正数,因此填充值可以为0-xNaN,...

我能想到的最好的方法是基于循环的:

maxNumElem = 0;
for i=in(1,1):in(end,1)
    maxNumElem = max(maxNumElem,numel(find(in(:,1)==i)));
end

out = zeros(maxNumElem,in(end,1)-in(1,1));
for i=in(1,1):in(end,1)
    tmp = in(in(:,1)==i,2);
    out(1:length(tmp),i) = tmp;
end

解决方案

以下示例中的任何一种都假定 in的第1列已排序.如果不是这种情况,请首先根据该标准对in进行排序:

in = sortrows(in,1);

方法1(使用accumarray)

  1. 使用 mode 计算所需的行数;
  2. 使用 accumarray 来收集与每个值对应的值列,末尾用零填充.结果是一个单元格;
  3. 水平串联所有单元格的内容.

代码:

[~, n] = mode(in(:,1));                                                 %//step 1
out = accumarray(in(:,1), in(:,2), [], @(x){[x; zeros(n-numel(x),1)]}); %//step 2
out = [out{:}];                                                         %//step 3

或者,可以使用 histc 完成步骤1

n = max(histc(in(:,1), unique(in(:,1))));                               %//step 1

或使用accumarray:

n = max(accumarray(in(:,1), in(:,2), [], @(x) numel(x)));               %//step 1

方法2(使用sparse)

使用 @Dan的答案生成行索引向量,然后使用 sparse :

a = arrayfun(@(x)(1:x), diff(find([1,diff(in(:,1).'),1])), 'uni', 0); %//'
out = full(sparse([a{:}], in(:,1), in(:,2)));

for an input matrix

in = [1 1;
      1 2;
      1 3;
      1 4;
      2 5;
      2 6;
      2 7;
      3 8;
      3 9;
      3 10;
      3 11];

i want to get the output matrix

out = [1 5 8;
       2 6 9;
       3 7 10;
       4 0 11];

meaning i want to reshape the second input column into an output matrix, where all values corresponding to one value in the first input column are written into one column of the output matrix.

As there can be different numbers of entries for each value in the first input column (here 4 values for "1" and "3", but only 3 for "2"), the normal reshape function is not applicable. I need to pad all columns to the maximum number of rows.

Do you have an idea how to do this matlab-ish?

The second input column can only contain positive numbers, so the padding values can be 0, -x, NaN, ...

The best i could come up with is this (loop-based):

maxNumElem = 0;
for i=in(1,1):in(end,1)
    maxNumElem = max(maxNumElem,numel(find(in(:,1)==i)));
end

out = zeros(maxNumElem,in(end,1)-in(1,1));
for i=in(1,1):in(end,1)
    tmp = in(in(:,1)==i,2);
    out(1:length(tmp),i) = tmp;
end

解决方案

Either of the following approaches assumes that column 1 of in is sorted, as in the example. If that's not the case, apply this initially to sort in according to that criterion:

in = sortrows(in,1);

Approach 1 (using accumarray)

  1. Compute the required number of rows, using mode;
  2. Use accumarray to gather the values corresponding to each column, filled with zeros at the end. The result is a cell;
  3. Concatenate horizontally the contents of all cells.

Code:

[~, n] = mode(in(:,1));                                                 %//step 1
out = accumarray(in(:,1), in(:,2), [], @(x){[x; zeros(n-numel(x),1)]}); %//step 2
out = [out{:}];                                                         %//step 3

Alternatively, step 1 could be done with histc

n = max(histc(in(:,1), unique(in(:,1))));                               %//step 1

or with accumarray:

n = max(accumarray(in(:,1), in(:,2), [], @(x) numel(x)));               %//step 1

Approach 2 (using sparse)

Generate a row-index vector using this answer by @Dan, and then build your matrix with sparse:

a = arrayfun(@(x)(1:x), diff(find([1,diff(in(:,1).'),1])), 'uni', 0); %//'
out = full(sparse([a{:}], in(:,1), in(:,2)));

这篇关于在Matlab中使用列方向零填充将向量重塑为矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆