Error matrix index is out of range for deletion?

1 view (last 30 days)
When running this piece of code I get the error
Matrix index is out of range for deletion.
Error in pco2checkm (line 111)
eval([vars_ '(elim)=[];']);
% code
vars=whos;
elim=[(find(condTemp>5.5 | condTemp<2.5))
(find(err==1))
(find(licorFlow>200 | licorFlow<40))
(find(H2OFlow>5 | H2OFlow<0.3))
(find(equPress+atmPress>1040 | equPress+atmPress<900))
(find(licorPress>1040 | licorPress<900))
(find(atmPress>1040 | atmPress<900))
(find(equTemp>32 | equTemp<-2))
(find(licorTemp>50 | licorTemp<10))
(find(diff(equTemp)>1 | diff(equTemp)<-1))
];
elim=sort(elim);
% delete repeats
elim(diff(elim)==0)=[];
for ii=1:size(vars,1)
vars_=eval(['vars(' num2str(ii) ').name;']);
eval([vars_ '(elim)=[];']);
clear vars_;
end
clear ii elim vars
I don't understand what I am doing wrong.
Thanks in advance
  3 Comments
Walter Roberson
Walter Roberson on 18 Sep 2018
Are each of those variables the same size as the others?
By the way instead of deleting repeats like that, use unique() instead of sort()
Stephen23
Stephen23 on 18 Sep 2018
@KSSV: you don't need to wait for me, I am sure that you are capable of writing a good piece of advice on this topic. I am just happy if people find this tutorial useful:

Sign in to comment.

Answers (1)

Guillaume
Guillaume on 18 Sep 2018
I don't understand what I am doing wrong
Lots!
As KSSV commented, first is the use of eval. eval is typically used by people who don't know better to dynamically generate variable names. This is never a good idea (search Stephen Cobeldick's answers to learn more) but in your case, the first eval is not even used for that. Instead it's used for plain indexing where it is totally unnecessary. The only thing it does is obfuscate the code and make it harder to follow what is happening.
Secondly, your code indiscriminately tries to delete some elements from all the variables in your workspace. It never check that the variable it deletes from actually has that many elements to start with, so it's no wonder that you get an error. I suspect that you have a variable in workspace that you didn't mean to delete from.
Then, we have the computation of the indices to delete that is unnecessarily complicated. Assuming all the variables you're testing have the same size, then none of the find are necessary. And the whole business of sorting and deleting repeat (which can be achieved more simply with unique) is really unnecessary.
I'm assuming what you're trying to do is to delete some elements from your variables used to build elim and possibly some others. Keeping them as individual variables, you would indeed have to use eval to perform the deletion or hardcode all the names in your code. That is always going to be fragile. The best solution would be to regroup all these variables together in a table. Your deletion then becomes simple row deletions which don't require eval.
To build the table, assuming your variables are column vectors (if row vectors, transpose them)
T = table(condTemp, err, licorFlow, H2OFlow, equPress, atmPress, licorPress, equTemp, licorTemp); %with possibly more variables
If there's really a lot of variables in the workspace and all of them belong to the dataset, then using eval to generate the table could be acceptable:
vars = whos; %You have to be sure that all the variables in the workspace are the same size
T = eval(sprintf('table(%s)', strjoin({vars.name}, ','))); %more complex code required if variables are row vector
Once the table is built, the computation of elim can be done more or less the same way you've done. Again, find is completely unnecessary. Use a logical array instead of indices:
elim = T.condTemp>5.5 | T.condTemp<2.5 | ...
T.err==1 | ...
T.licorFlow>200 | T.licorFlow<40 | ...
T.H2OFlow>5 | T.H2OFlow<0.3 | ...
T.equPress+T.atmPress>1040 | T.equPress+T.atmPress<900 | ...
T.licorPress>1040 | T.licorPress<900 | ...
T.atmPress>1040 | T.atmPress<900 | ...
T.equTemp>32 | T.equTemp<-2 | ...
T.licorTemp>50 | T.licorTemp<10 | ...
[false; diff(T.equTemp)>1 | diff(T.equTemp)<-1)];
And the deletion is trivial:
T(elim, :) = [];
  2 Comments
Stephen23
Stephen23 on 18 Sep 2018
"If there's really a lot of variables in the workspace and all of them belong to the dataset..."
it is worth asking how they all got into the workspace in the first place. Most likely this whole obfuscated inefficient code could be trivially avoided by fixing the problem at its source, rather than trying to "fix" it later. For example, by simply load-ing into an output variable instead of directly into the workspace:
S = load(...);
Fixing your code where those variables are all defined is the best solution (best in the sense neater, no data duplication, more efficient, less buggy, etc.).
Guillaume
Guillaume on 18 Sep 2018
@Stephen, Indeed! I was going to mention that and forgot.
Depending on how these variables were loaded, it could be that creating the table could be trivially achieved by readtable.
More details required on how the mess started indeed.

Sign in to comment.

Categories

Find more on Matrices and Arrays in Help Center and File Exchange

Tags

Community Treasure Hunt

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

Start Hunting!