Azzera filtri
Azzera filtri

Change a value after a maximum five-consecutive column of zero

2 visualizzazioni (ultimi 30 giorni)
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 Commenti
Jalu Naradi
Jalu Naradi il 9 Mag 2018
Sorry, it was my mistake. I edit the example so that there are 6 consecutive zeros now before 1
Jalu Naradi
Jalu Naradi il 10 Mag 2018
@Jan, the matrix size is [3000,1000]. Thank you

Accedi per commentare.

Risposta accettata

Guillaume
Guillaume il 9 Mag 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 Commenti
Guillaume
Guillaume il 14 Mag 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).

Accedi per commentare.

Più risposte (2)

Jan
Jan il 9 Mag 2018
Modificato: Jan il 9 Mag 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
Ameer Hamza il 9 Mag 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 Commenti
Guillaume
Guillaume il 9 Mag 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.
Jalu Naradi
Jalu Naradi il 10 Mag 2018
Thank you Ameer for your answer. As Guillaume mentioned above, there are several patterns that acceptable here.

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by