Change a value after a maximum five-consecutive column of zero
1 view (last 30 days)
Show older comments
I have a matrix [3000,1000] which has only 0, 1, and -1. If there is a -1 in a row followed by a (maximum) consecutive five-columns of zeros then followed by 1, this 1 value should change to 2.
I am looking for the fastest way to do it in Matlab. Is there anyway without a loop? if not, what is the best way?
For example
A = [1 0 0 -1 0 0 0 0 1 0 0 -1 0 0 1;
0 -1 0 0 0 0 0 0 1 -1 0 1 0 0 -1];
% I would like to change matrix A as follow
A = [1 0 0 -1 0 0 0 0 2 0 0 -1 0 0 2;
0 -1 0 0 0 0 0 0 1 -1 0 2 0 0 -1 ];
Thanks in advance,
3 Comments
Accepted Answer
Guillaume
on 9 May 2018
I don't think this can be done more efficiently than with a loop over the rows:
for row = 1:size(A, 1)
col = find(A(row, :));
tochange = diff(col) <= 5 & A(row, col(1:end-1)) == -1 & A(row, col(2:end)) == 1;
A(row, col([false, tochange])) = 2;
end
4 Comments
Guillaume
on 14 May 2018
The result of diff is a vector with one less element than col. tochange(1) actually corresponds to col(2|, so I just prepend false to vector (since the 1st element is never going to have to be changed anyway).
More Answers (2)
Jan
on 9 May 2018
Edited: Jan
on 9 May 2018
A = [1 0 0 -1 0 0 0 0 1 0 0 -1 0 0 1; ...
0 -1 0 0 0 0 0 1 -1 0 1 0 0 1 0];
[s1, s2] = size(A);
Av = reshape(A.', 1, []); % Convert it to 1 vector
for k = 0:5
index = strfind(Av, [-1, zeros(1, k), 1]);
index = index(mod(index, s2) < s2 - k); % Omit matches at end of row
Av(index + k + 1) = 2;
end
B = reshape(Av, s2, []).';
Ameer Hamza
on 9 May 2018
This is an approach to modify an identify an arbitrary pattern and modify a value, Using for loop and comparing them by converting them to char array.
A = [1 0 0 -1 0 0 0 0 1 0 0 -1 0 0 1;
0 -1 0 0 0 0 0 1 -1 0 1 0 0 1 0];
pattern = [-1 0 0 0 0 1];
strA = num2str(A+1); % +1 is added to remove negative signs for easy manipulation as strings
strPattern = strrep(num2str(pattern+1), ' ', '');
for i=1:size(A,1)
index = strfind( strrep(strA(i,:), ' ', ''), strPattern) + length(pattern) -1;
if ~isempty(index)
A(i, index) = 2;
end
end
2 Comments
Guillaume
on 9 May 2018
Note that you don't need to convert numbers to char to use strfind. Despite not being actually documented, strfind works just as well for detecting patterns of numbers
strfind(A(i, :), [-1 0 0 0 0 0 1])
The problem here is that several patterns are acceptable, [-1 1], [-1 0 1], ..., [-1 0 0 0 0 0 1], so a pattern search is not particularly useful. I guess a regexp would work (which does requires a conversion to char) but I'm not convinced the extra complexity and time taken by the regex would be better than the simple for loop I've detailed.
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!