How to remove cell array satisfying specific conditions
4 vues (au cours des 30 derniers jours)
Afficher commentaires plus anciens
Hi all,
I have a cell array with n vectors of different lengths m. I want to remove the cells, whose vectors satisfy a specific condition for which all the elements of the individual vectors need to be scanned. Something like that:
for c = 1 : length(cutForce)
for d = round(length(cutTime{c})/4) : round(3*length(cutTime{c})/4)% searching for data between the 1st and 3rd fourth of the vector
if min(cutForce{c}(d)) < 300
cutForce(c) = [];
end
end
end
Unfortunately the code doesn't work. I am new to programming. Help me please.
0 commentaires
Réponse acceptée
Guillaume
le 25 Sep 2015
Modifié(e) : Guillaume
le 26 Sep 2015
There are two issues with your code:
- You're performing the min on just one element, since d is scalar. You either meant to just compare the element value to 300 (without min):
for d = ...
if cutForce{c}(d) < 300
...
or you meant to use min, in which case you did not need a loop:
d = round(...) : round(...) %d is just a list of indices
if min(cutForce{c})d) < 300
...
- More importantly, you are removing element of a sequence while you're iterating over an index of the sequence which does not know that elements have been remove. For example, imagine that when c = 2 your condition is true. You delete the second element, so third element becomes 2nd, 4th becomes third, etc. On the next pass of the loop, c becomes 3, which was the 4th element before. So you never test the original 3rd. Furthermore, when you reach the end, there's less elements than expected, so you're going to get an indexing error. The solution to this is to gather the list of indices to remove in the loop and perform the deletion afterward:
todelete = false(size(cutForce)); %vector that keeps track of which elements to delete
for c = 1:numel(cutForce) %I prefer numel to length as it works with n-d arrays.
testvector = cutForce{c}(round(numel(cutTime{c})/4) : round(3*numel(cutTime{c})/4));
%the above can also be written using the end keyword:
%testvector = cutForce{c}(round(end/4) : round(3*end/4));
todelete(c) = min(testvector) < 300; %either true or false
end
cutForce(todelete) = []; %delete all elements at once after the loop
todelete = cellfun(@(v) min(v(round(end/4):round(3*end/4))) < 300, cutForce);
cutForce(todelete) = [];
3 commentaires
Guillaume
le 26 Sep 2015
There was a stupid mistake in both of my codes that I've now fixed.
With the example matrices that you've posted 3 elements of cutForce are removed.
Plus de réponses (1)
the cyclist
le 25 Sep 2015
Modifié(e) : the cyclist
le 25 Sep 2015
I have not looked at the details of your algorithm. One likely problem is that as you remove elements of the cell array inside your for loop, the index c begins to point to the wrong element. For example, if you happen to remove the first element, then the next time through the loop, c = 2 refers to the 2nd element of the shortened cell array, which is actually the 3rd element of the original vector.
There are a couple solutions. The easier one to understand for a beginner is to, in your for loop, only identify and store the elements you want to remove (say, in variable indicesToRemove), but don't remove them yet. Then, as a second step, do something like
cutForce(indicesToRemove) = [];
The more sophisticated way to do this is to use the cellfun command, which would allow you to test the condition on all cell array elements at once.
Voir également
Catégories
En savoir plus sur Loops and Conditional Statements dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!