Is it possible to replace ranges of a matrix elements using indices from two vectors?
古いコメントを表示
Hi,
I have a matrix of size 5x5 all the elements of which are zeros. I would like to replace some of these zeros with ones. The elements that I want to replace are referenced by two vectors a & b each of size (5 x 1). These two vectors point to the beginning and ending column indices of the range to be replaced. These ranges vary from one row to another. I tried using X(:,a:b)=1, but it only uses the first value in these vectors. I don't know how to modify my code so that the ranges vary by each row.
> X=zeros(5,5)
X =
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
> a=[2,3,1,3,4]'
a =
2
3
1
3
4
> b=[4,3,2,4,5]'
b =
4
3
2
4
5
> X(:,a:b)=1
X =
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
How can I get the result look like this?
X =
0 1 1 1 0
0 0 1 0 0
1 1 0 0 0
0 0 1 1 0
0 0 0 1 1
Thanks! Hawre
採用された回答
その他の回答 (1 件)
Andrei Bobrov
2011 年 5 月 4 日
more variant
indcol = ones(5,1)*(1:5);
X = +(a(:,ones(5,1))<=indcol & b(:,ones(5,1))>=indcol)
and
C = arrayfun(@(x,y,z)[z*ones(y-x+1,1), (x:y).'],a,b,(1:length(a))','un',0);
C = cat(1,C{:});
X(sub2ind(size(X),C(:,1),C(:,2))) = 1;
6 件のコメント
Oleg Komarov
2011 年 5 月 4 日
+ 1 for the first, also bsxfun version:
indcol = 1:5;
X = bsxfun(@le,a,indcol) .* bsxfun(@ge,b,indcol);
P.S: I think + is obscure as compared to double.
Oleg Komarov
2011 年 5 月 4 日
Timings of Matt's LOOP and bsxfun LOGICAL (more or less the same):
N = 5000;
a = ceil(rand(N,1)*N);
b = min(a+round(rand(N,1)*N),N);
times = zeros(100,2);
for n = 1:100
tic
indcol = 1:N;
X1 = bsxfun(@le,a,indcol) .* bsxfun(@ge,b,indcol);
times(n,1) = toc;
end
for n = 1:100
tic
X2 = zeros(N);
for ii = 1:N
X2(ii,a(ii):b(ii)) = 1;
end
times(n,2) = toc;
end
isequal(X1,X2)
mean(times(2:end,:))
Matt Fig
2011 年 5 月 4 日
When I put this into a function, the FOR loop is more than 2.5 times as fast (using a modified loop from my original post...). Did you have your timings in a function or a script, Oleg? I am using 2007b also, so something may have changed....
function [] = address_vects()
N = 4000;
T = [0 0];
for jj = 1:100
a = ceil(rand(N,1)*N);
b = min(a+round(rand(N,1)*N),N);
tic
X = false(N,N);
for ii = 1:size(X,1)
X(ii,a(ii):b(ii)) = 1;
end
X = double(X); % Convert to double.
T(1) = T(1) + toc;
tic
% indcol = ones(N,1)*(1:N);
% X1 = +(a(:,ones(N,1))<=indcol & b(:,ones(N,1))>=indcol);
indcol = 1:N;
X1 = bsxfun(@le,a,indcol) .* bsxfun(@ge,b,indcol);
T(2) = T(2) + toc;
end
reltime = T/min(T)
>> address_vects
reltime =
1 2.6987
Oleg Komarov
2011 年 5 月 4 日
Vista 32b r2010b. It may be multithreading of bsxfun.
reltime =
1.0497 1.0000
Matt Fig
2011 年 5 月 4 日
O.k., that is what I thought. Still, 5% is pretty close. I wish BSXFUN had built-in string inputs (think CELLFUN). Then I bet this solution would be MUCh faster.
Hawre Jalal
2011 年 5 月 4 日
カテゴリ
ヘルプ センター および File Exchange で Loops and Conditional Statements についてさらに検索
製品
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!