【问题标题】:Matlab: superimposing rows of different lengths onto matrixMatlab:将不同长度的行叠加到矩阵上
【发布时间】:2013-11-24 22:04:24
【问题描述】:

如何将不同长度的行叠加到 Matlab 中的矩阵上?也就是说,我希望矩阵 A 的第 z 行中的第一个 x 个元素和最后一个 y 个元素为零,其中 x 和 y 在长度为 Z 的两个列向量中指定(因此对应于矩阵的行数一种)。我只能从简单循环的角度考虑解决方案,但我正在寻找一种更优雅的解决方案,避免使用循环,因为这段代码需要在主循环中运行数千次。

编辑

正如@randomatlabuser 所证实的,这就是提问者想要在没有循环的情况下做的事情:

M = 1e4; N = 1e3; A = randn(M, N);
x = randi([0, N], [M, 1]);
y = randi([0, N], [M, 1]);
for hh = 1:M
  A(hh, 1:x(hh)) = 0;
  A(hh, (N - y(hh) + 1):N) = 0;
end

【问题讨论】:

  • 你想如何填充剩余的(非零)值?能举个简单的例子吗?
  • A 已经被填充了,但是我想用零替换每行的第一个 x 和最后一个 y 元素数,其中 x 和 y 对于每一行都是不同的,并在两个列向量中定义。
  • x 和 y 在主循环的所有迭代中都相同吗?
  • @user3029330 下次如果您已经有了想要改进的可行解决方案,请将其包括在内,以防止混淆或重复工作。

标签: matlab matrix


【解决方案1】:

你可以这样做:

A = rand(4,6); %// example data
x = [1; 2; 1; 3]; %// example data
y = [1; 2; 1; 2]; %// example data

[M N] = size(A);
col = 1:N;
B = A.* ( bsxfun(@gt, col, x) & bsxfun(@le, col, (N-y)) );

本例中的结果是:

>> A

A =

    0.0168    0.8797    0.7367    0.9859    0.5385    0.9745
    0.9274    0.4161    0.0567    0.0649    0.7961    0.1616
    0.3935    0.8690    0.8386    0.0308    0.5494    0.5525
    0.7615    0.1895    0.0002    0.0919    0.7167    0.6101

>> B

B =

         0    0.8797    0.7367    0.9859    0.5385         0
         0         0    0.0567    0.0649         0         0
         0    0.8690    0.8386    0.0308    0.5494         0
         0         0         0    0.0919         0         0

如果 xy 在主循环的所有迭代中都相同,则可以通过在循环之前计算掩码来节省时间:

[M N] = size(A);
col = 1:N;
mask = bsxfun(@gt, col, x) & bsxfun(@le, col, (N-y));

然后在每次迭代中,您只需应用预先计算的掩码:

B = A.*mask;

【讨论】:

  • +1 这种方法有效。但是,当 M 和 N 很大时,它似乎比循环慢 - 还有其他方法吗?如果 M = 1e4;N = 1e3;A = randn(M, N);,循环在 0.630966 秒内完成,ndgrid 在 1.791081 秒内完成。
  • @randomatlabuser 谢谢! ndgrid 使用更多内存(因为它会生成行和列的所有组合),这可能是导致大尺寸运行时间增加的原因。
  • @randomatlabuser 我已将ndgrid 替换为bsxfun。现在运行时间要小得多。感谢您的提醒!尽管如此,循环似乎更快
  • 在我的电脑上bsxfun 的运行速度比loop 快:平均0.50 秒对0.67
  • @user3029330 如果您可以在一个简单的单循环中完成,那么避免循环通常不会有太多好处。但是,如果速度确实是一个问题,那么bsxfun 通常是这里所示的方法。
【解决方案2】:

你想做的是:

M = 1e4; N = 1e3; A = randn(M, N);
x = randi([0, N], [M, 1]);
y = randi([0, N], [M, 1]);
for hh = 1:M
  A(hh, 1:x(hh)) = 0;
  A(hh, (N - y(hh) + 1):N) = 0;
end

但没有循环,对吧?

【讨论】:

  • 是的,完全正确。可以这样做吗?也许使用某种巧妙的线性索引形式?
  • 我明白你为什么发布这个,但恐怕这不是一个答案。我已将其包含在问题中(它属于哪里)。 -- 请立即清理这个“答案”。
猜你喜欢
  • 2018-11-08
  • 1970-01-01
  • 1970-01-01
  • 2011-03-04
  • 2010-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多