我有一个订单100*5
的矩阵。现在的目标是用特定范围内的随机整数填充矩阵的每列。现在问题是每列的随机数范围都会发生变化。例如,对于第一列,范围是1到100,第二列是-10到1,依此类推到第5列。
这是我尝试过的:
b = [0,100;-10,1;0,1;-1,1;10,20]
range = b(:,2) - b(:,1)
offset = b(:,1)
A = round(rand(100,5) * range - offset)
来自this问题。但是这会产生错误,
使用*内部矩阵尺寸时出错必须同意。
可能导致此问题以及如何解决问题?
答案 0 :(得分:4)
让bsxfun
这个东西!
A = round(bsxfun(@minus,bsxfun(@times,rand(100,5) ,range'), offset'))
答案 1 :(得分:3)
作为替代解决方案,您可以使用repmat
来完成已有的内容:
b = [0, 100; -10, 1; 0, 1; -1, 1; 10, 20].';
rng = b(2, :) - b(1, :);
ofst = b(1, :);
A = round(rand(100,5) .* repmat(rng, 100, 1) + repmat(ofst, 100, 1));
您不必定义rng
或ofst
,这可以简单地写成:
A = round(rand(10,5) .* repmat(diff(b), 10, 1) + repmat(b(1,:), 10, 1));
出于好奇,我写了这个快速基准*来与Ander的bsxfun
方法进行比较。似乎bsxfun
有一些初始开销,这意味着5列(自己测试其他情况)和少于几千行,repmat
更快。在此之上,repmat
创建额外的大型数组可能会导致速度变慢,我们会看到bsxfun
更快。
对于未来的读者,如果这不适用于您: broadcasting introduced from R2016b您可能会发现您可以完全使用bsxfun
和repmat
躲闪。
*基准测试代码。在Windows 64位R2015b上测试,您的里程可能会有所不同等。
function benchie()
b = [0, 100; -10, 1; 0, 1; -1, 1; 10, 20].';
Tb = [];
Tr = [];
K = 20;
for k = 1:K
n = 2^k;
fb = @()bsxfunMethod(b,n);
fr = @()repmatMethod(b,n);
Tb(end+1) = timeit(fb);
Tr(end+1) = timeit(fr);
end
figure; plot(2.^(1:K), Tb, 2.^(1:K), Tr); legend('bsxfun', 'repmat');
end
function bsxfunMethod(b, n)
round(bsxfun(@minus,bsxfun(@times, rand(n,5), diff(b)), b(1,:)));
end
function repmatMethod(b, n)
round(rand(n,5) .* repmat(diff(b), n, 1) + repmat(b(1,:), n, 1));
end
答案 2 :(得分:2)
您可以使用randi
执行此操作,将b
行传递到其第一个参数:
b = [0,100;-10,1;0,1;-1,1;10,20];
A = zeros(100,5);
f=@(ii)randi(b(ii,:),100,1);
for ii = 1:size(A,2)
A(:,ii) = f(ii);
end
我怀疑有一种方法可以在没有循环遍历行/列的情况下执行此操作,可能使用bsxfun
。
答案 3 :(得分:2)
您可以使用arrayfun
,即使我没有看到使用循环和编写更易读的代码有任何损害,如史蒂夫的回答。
A = cell2mat(arrayfun(@(imin, imax) randi([imin, imax], 100, 1), b(:,1), b(:,2), 'uni', 0)')