【问题标题】:Matlab - Create a vector using another vector as the limitsMatlab - 使用另一个向量作为限制创建一个向量
【发布时间】:2014-11-09 04:09:15
【问题描述】:

假设我有以下列向量Z

 1  53  55  57  60  64  68  70  71  72  74  76  77  78  79  80  255

我想用它来创建一个矩阵,这样每一行将包含Z中两个相邻元素之间(包括)之间的所有数字

所以输出矩阵应该是这样的:

1 2 3 .... 53
53    54   55
55    56   57
57    58   60
....
80  81 ... 255

我一直在寻找类似的东西,但找不到。

谢谢

【问题讨论】:

  • 它怎么可能是一个二维数字矩阵,它的每行元素数量不相等。还是您在寻找元胞数组?
  • 好点。 (在转换到向量编程时遇到问题。用零填充以匹配最大的行?
  • 是的,可以做填充。那么,最后填充?
  • 另外,Z 总是排序的吗?
  • 是的,总是排序的,总是从 1 开始,以 255 结束

标签: matlab vector


【解决方案1】:

看看这是否适合你 -

lens = diff(Z)+1;
mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
array1 = zeros(size(mask1));
array1(mask1) = sort([1:255 Z(2:end-1)]);
out = array1.'; %//'# out is the desired output

【讨论】:

  • 这正是我所需要的。谢谢!
  • @Lablabla 欢迎来到矢量处理的世界! :)
  • :) 谢谢。非常感谢
  • @Divakar 避免循环总是值得的吗?我看到你在矢量化方面做得很好,你能看看我做的比较吗?提前致谢。
  • @Arpi 这可能不是使用矢量化的最佳情况,因为行长度之间的差异有点偏高。但是我一直有矢量化的习惯,我猜它变得更容易了。此外,我对 GPU 和并行计算感兴趣,并且矢量化可以完美地工作,因为重复索引到 gpu 数组确实很昂贵。因此,归根结底,这完全取决于您要处理的数据类型(最重要的因素)、您的硬件是什么以及其他一些事情。
【解决方案2】:

试试这个打破bsxfun的单调:):

d = diff(Z);
N = max(d)+1;

R = zeros(length(Z)-1,N);

for i = 1:length(Z)-1
    R(i,1:1+d(i)) = Z(i):Z(i+1);
end

编辑:

我知道普遍的共识是人们总是应该尽量避免在 Matlab 中出现循环,但这对这个例子有效吗?我知道这是一个广泛的问题,所以让我们专注于这个特定问题并将bsxfun 与 JIT 循环进行比较。比较两种建议的解决方案:

用于测试的代码:

Z =  [1  53  55 57  60  64  68  70  71  72  74  76  77  78  79  80  255];

%[1  3  4, 6];
nn = round(logspace(1,4,10));
tm1_nn = zeros(length(nn),1);
tm2_nn = zeros(length(nn),1);

for o = 1:length(nn)

    tm1 = zeros(nn(o),1);
    tm2 = zeros(nn(o),1);
    % approach1
    for k = 1:nn(o)+1
        tic
        d = diff(Z);
        N = max(d)+1;

        R = zeros(length(Z)-1,N);

        for i = 1:length(Z)-1
            R(i,1:1+d(i)) = Z(i):Z(i+1);
        end
        tm1(k) = toc;
    end


    %approach 2
    for k = 1:nn(o)+1
        tic
        lens = diff(Z)+1;
        mask1 = bsxfun(@le,[1:max(lens)]',lens); %//'
        array1 = zeros(size(mask1));
        array1(mask1) = sort([1:255 Z(2:end-1)]);
        out = array1.';
        tm2(k) = toc;
    end

    tm1_nn(o) = mean(tm1);%sum(tm1);%mean(tm1);%
    tm2_nn(o) = mean(tm2);%sum(tm2);%mean(tm2);%

end

semilogx(nn,tm1_nn, '-ro', nn,tm2_nn, '-bo')
legend('JIT loop', 'bsxfun')
xlabel('log_1_0(Number of runs)')
%ylabel('Sum execution time')
ylabel('Mean execution time')
grid on

我之前遇到过其他循环更快的任务。 (或者我搞砸了比较?)

【讨论】:

  • 看起来合法,您可以添加的东西很少,这不一定会大大改变运行时,而是会使运行时更加一致 - 1)在开始时热身tic/toc,您可以查找 here 和 2)在一种方法结束后清除使用的变量。
  • 感谢您的意见和建议!
  • 关于如果性能是最高标准,每行长度的差异如何决定是否进行矢量化的主题,您可以尝试更一致(在更少的情况下)长度差异)输入数据 - Z = [1:10:255 255]。有了这个,矢量化代码会更好地工作,所以只是展示数据如何在该决策中发挥重要作用。
  • 有趣的是,与原始问题相比,建议的Zbsxfun 和循环切换位置。我会记住矩阵“细长”的这种影响。谢谢!
  • 哈哈,“苗条”这个词不错,以后可以参考! :) 谢谢你的造币!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-18
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 2012-03-13
相关资源
最近更新 更多