Matlab:将矩阵重塑为一维数组,将重叠的元素加在一起



下面是一个示例矩阵:

x=[1,2,3,4,5;6,7,8,9,10;11,12,13,14,15]'; % 1:5 in 1st column, 6:10 in 2nd etc

所以我有:

x=
1 6  11
2 7  12
3 8  13
4 9  14
5 10 15

我想将给定列的元素的上半部分(不包括中间元素)与前一列的下半部分重叠,从而在重叠中添加元素。第一列和最后一列显然是例外(第一列没有前一列,也没有任何东西可以添加到最后一列)

在上面的简单示例中,为了清楚起见,我重写了该行以显示要重叠的数字:

x=[1,2,3,4,5;
         6,7,8,9,10;
               11,12,13,14,15]';

因此,我希望结果是:

y=[1;2;3;4+6;5+7;8;9+11;10+12;13;14;15];

现在,这只是一个非常简单的例子。生成的代码需要通过大数据进行良好的扩展/高效运行。矩阵的大小可能约为 120000x600,我认为生成的 1D 数组约为 37000000x1

原始问题的答案(添加移位):

这可以按如下方式完成:

  1. 生成一个索引向量(ind),使得要求和的x条目具有相同的索引。这可以通过 bsxfun .索引可以计算一次,然后重用于不同的x向量(索引不依赖于x)。
  2. 使用该索引向量对accumarray求和:

法典:

n = ceil(size(x,2)/2);
ind = bsxfun(@plus, 1:size(x,2), (0:size(x,1)-1).'*n); %'// step 1. Valid for any x
y = accumarray(ind(:), x(:));                          % // step 2. Depends on x

回答编辑的问题(添加移位):

转置x并按上述方式继续操作:

x = x.';
n = ceil(size(x,2)/2);
ind = bsxfun(@plus, 1:size(x,2), (0:size(x,1)-1).'*n);for any x
y = accumarray(ind(:), x(:));

加法可以用一个矩阵矩阵加法计算,然后重新排序结果。

矩阵

矩阵加法的形式为

x = [1  2  3  4  5;
     6  7  8  9  10;
     11 12 13 14 15];
A = [4 5; 9 10] + [6 7; 11 12]

第一行和最后一行以及中间列保持不变。这将生成以下代码:

x=[1,2,3,4,5;6,7,8,9,10;11,12,13,14,15]';
x = x.';
n = ceil(size(x,2)/2);
m = floor(size(x,2)/2);
A = [x(1:(end-1),(m+1):n) x(2:end,1:m)+x(1:(end-1),(n+1):end)]';
y = [x(1,1:m) A(:)' x(end,(m+1):end)];

结果是y = 1 2 3 10 12 8 20 22 13 14 15

x=rand(120000,600)需要 1.3 秒

这可能是一种方法 -

%// Get size
[n,m] = size(x)
%// Indices of first overlapping elements and its length
first_overlap = ceil(n/2)+1:n
overlap_len = numel(first_overlap)
%// Store the last elements of overlapping length to be appended at final stage
rem_ele = x(end-numel(first_overlap)+1:end)
%// Indices of overlapping elements across all columns
idx = bsxfun(@plus,first_overlap(:),[0:m-2]*n)
%// Do summations of overlaps and store back tto the next group of overlaps
x(idx(:)+overlap_len) = x(idx(:)) + x(idx(:)+overlap_len)
%// Remove elements from the previous overlaps
x(end-overlap_len+1:end,:)=[]
%// Output array after appending rem_ele to column vector version of modified x
out = [x(:) ; rem_ele(:)]

可能不是最具可扩展性的解决方案,但可能是可读且直观的解决方案:

% Split the matrix into three parts
left  = x(:,1:floor(end/2));
mid   = x(:,floor(end/2)+1:ceil(end/2));
right = x(:,ceil(end/2)+1:end);
% Extend the middle part by one, note that this works even if mid is empty
mid(end+1,:) = nan;
% Construct a new matrix by summing up left and right parts
X = [left(1,:); ...
     left(2:end,:) + right(1:end-1,:); ...
     right(end,:)];
% Add the midpoints back
X=[X, mid].';
% Reshape into vector and remove the possible extra mid point 
y = X(1:end-~isempty(mid));

最新更新