【问题标题】:Mixing 3D arrays into a bigger 3D array将 3D 阵列混合成更大的 3D 阵列
【发布时间】:2018-12-27 16:23:53
【问题描述】:

我希望用来自矩阵“P”和“Q”的数据填充一个 N x M x W 矩阵“S”。它们在下面定义并在附图中说明。此外,我们确定 n_1 + n_2 = N, m

S = zeros(M,N,W);
P = rand(m,n_1,W);
Q = rand(m,n_2,W);

我希望以 3 个其他矩阵(“Line_num”、“P_col”和“Q_col”)指定的方式组合“P”和“Q”,如下所述和所附图像的中间部分。

P_col = randperm(N); P_col = P_col(1:n_1);          % 1 x n_1 matrix
Q_col = setxor(P_col, 1:1:N);           % 1 x n_2 matrix

Line_num 是由 W 个向量组成的矩阵,形式为 aa:1:bb,其中 bb-aa = m,并且为每个向量随机选择 aa。

重要的是,在这种情况下,所有这些矩阵中沿第 3 维的数据代表 W 个不同的测试用例,数据各不相同,不能相互混合。

要填写“S”,可以分两个合乎逻辑的步骤进行(尽管如果可以一次性完成,我会很高兴)

  1. 将 Q 和 P 组合成一个形状为 m x N x W 的中间矩阵 Y 交织他们的列。 “Q_col”中指定的列是 取自 Q(使用向量索引)并放入矩阵 Y(使用 向量值)。 P也是如此。

  2. 对于组成 Line_num 的每个 W 向量和组成 S 的数组, 使用向量 Line_num 中的值将 Y 展开到 S中的相应行,同时保持从上到下 顺序。

我希望在没有 for 循环的情况下实现这一点,因为我希望“矢量化”我的代码,从而提高其运行速度。

我看过this 帖子和this 帖子,这与我想要的相似。然而,它们更简单,因为要提取的数字是恒定的。也许类似的东西是合适的?

感谢您的帮助:)

Link to the image aforementioned


编辑:这是一个带有我想要的 for 循环的示例代码(我的问题是我想摆脱循环)

W = 4;
N = 10; n_1 = 4; n_2 = 6;
M = 20; m = 5;

P_col = [1,3,5,8];                      % 1 x n_1 matrix
Q_col = setxor(P_col, 1:1:N);           % 1 x n_2 matrix

line_num(:,:,1) = [1,5,10,15,18]; 
line_num(:,:,2) = [2,3,8,11,12]; 
line_num(:,:,3) = [4,7,8,14,19]; 
line_num(:,:,4) = [2,6,13,15,16]; 

S = zeros(M,N,W);
P = rand(m,n_1,W);
Q = rand(m,n_2,W);

for w=1:W
    line_num_I = line_num(:,:,w);
    S(line_num_I,Q_col,w) = Q(:,:,w);
    S(line_num_I,P_col,w) = P(:,:,w);
end

【问题讨论】:

  • 请提供您尝试过的 for 循环。有时代码比图像更能解释问题。
  • 考虑 P_col =randi(N,1,n_1); 创建重复的随机数。
  • 是的,我刚刚意识到这一点。感谢您指出。另外,我按照您的建议添加了示例代码。
  • 主要问题是line_num_I = line_num(:,:,w),因为它从 w 的值变为另一个

标签: matlab multidimensional-array indexing vectorization


【解决方案1】:

这是一个矢量化解决方案。我不确定它是否比循环版本更有效,特别是当数据量很大时。

 S (    reshape(line_num,[],1,W)       ...
        + ([Q_col-1 P_col-1]) * M      ...
        + (reshape(0:W-1,1,1,[]))*M*N  ...
   )                                   ...
   =                                   ...
   [reshape(Q,[],W);reshape(P,[],W)]; 

这里使用隐式扩展将下标转换为索引。等效地bsxfun 可用于计算线性索引:

S (                                     ...
    bsxfun(@plus,                       ...
        reshape(line_num,[],1,W),       ...
        bsxfun (@plus,                  ...
            ([Q_col-1 P_col-1]) * M,    ...
            (reshape(0:W-1,1,1,[]))*M*N ...
        )                               ...
    )                                   ...
  )                                     ...
  =                                     ...
  [reshape(Q,[],W);reshape(P,[],W)]; 

*Here你可以找到如何将3D索引转换为lindex。

【讨论】:

  • 非常感谢!这似乎很棒。但是,它似乎没有提供与其他两种方法完全相同的解决方案。你认为这可能是因为reshape(line_num,[],1,W) + ([Q_col-1 P_col-1]) * M + (reshape(0:W-1,1,1,[]))*M*N 是一个 3D 矩阵吗?
  • 没有完全一样的解决方案,你可以测试一下online。请看最后一行:isequal(S,SS).
  • 对不起,我的错。我忘记添加行SS = zeros(M,N,W);
【解决方案2】:

所以我最终找到了答案。对于那些可能感兴趣的人,上面的 for 循环可以替换为

% 1. Combine columns
mixed_col = zeros(m,N,W);
mixed_col(:,Q_col,:) = Q(:,:,:);
mixed_col(:,P_col,:) = P(:,:,:);
mixed_col = permute(mixed_col,[2,1,3]); % turn 3D matrix into 2D [1]
mixed_col = reshape(mixed_col,N,[],1)';

% 2. Combine lines
S = reshape(S,M*w,N,1); % turn 3D matrix into 2D [2]
line_num_v = permute(line_num + reshape((0:1:(W-1)).*M,1,1,W),[2,1,3]); % turn 3D matrix into 2D [3]
line_num_v = reshape(line_num_v,[],1,1);
S(line_num_v,:) = mixed_col(:,:); % combine using three 2D matrices
S = permute(reshape(S',N,M,W),[2,1,3]);

这涉及大量重塑,但我没有更简单的答案。 再次感谢您的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-14
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 2019-06-28
    • 1970-01-01
    • 2014-03-03
    相关资源
    最近更新 更多