I want to remove all the points that satisfy certain condition in matlab - matlab

current plot
I want to remove all those data points that lies between 5 & 10 on x axis and 0 & 500 on y axis.
givenData is a 10000X2 matrix with data.
I've written the following code. What mistake am I making here? Also is there a better way to do this?
for i=1:10000
if givenData(i,1)>5 && givenData(i,1)<10 && givenData(i,2)>0 && givenData(i,2)<500
givenData(i,:) = [];
end
end
plot(givenData(:,1),givenData(:,2),'b.','MarkerSize',5);hold
contour(xgrid,ygrid,Z,[4e-5, 4e-5],'EdgeColor',[1 0 0],'ShowText','on','LineWidth',2);
Any help is appreciated. Thank you.

You’re deleting elements from the array as you iterate through it, so the next element shifts over into the deleted spot and gets skipped in the checking.
To fix this, you can either skip the loop entirely and use logical indexing:
givenData(givenData(:,1)>5 & givenData(:,1)<10 & givenData(:,2)>0 & givenData(:,2)<500,:) = [];
or iterate through the array backwards:
for i = 10000:-1:1
In general, avoiding the loop allows MATLAB to perform operations more quickly, with the trade off that the index arrays take more memory to process.

Related

How can I speed up this loop?

I have a huge matrix (5000x5000x100) and I'm trying to smooth each index along the third dimension, but it takes HOURS. I am doing something inefficiently.
new_mat=zeros(size(my_mat));
for i = 1:length(mymat)
for j = 1:length(mymat)
new_mat(i,j,:) = wdenoise(squeeze(mymat(i,j,:)));
end
end
I know arrays and indexing would help but I'm not sure how to apply them here. Thanks for any help.
I don't have access to the newer Wavelet Toolbox needed for wdenoise, but since the function will operate across columns if you provide a matrix you should be able to remove the inner loop which may increase the speed a bit:
new_mat=zeros(my_mat)
for i = 1:length(mymat)
new_mat(i,:,:) = wdenoise(squeeze(mymat(i,:,:)));
end

MATLAB: How to determine whether any elements of an array are a certain a number

I am creating a simple minesweeper game for an assignment, but I am having trouble making the program determine whether the player has won or not. I am trying to find a function that determines whether any of the elements of A are equal to -2 and then use that in a while loop.
I have a simplified test code that I have been using to try to do this, but I can't find any functions that do what I want to do.
With everything I've tried so far, it either just keeps asking for more input even when it should say that the game is over, or it skips the while loop entirely. The last thing probably happens because all the elements of the start array are equal.
I have looked at xor, unique, setdiff, intersect, ismember isempty, and probably a couple more that I can't remember.
As this is not the complete code, I have just answered yes to the flag question every time in order to change all the elements from -2 to -3.
I also know that this wouldn't be the best way to determine whether the player has won or not, as it doesn't take into consideration if all the flags are placed correctly, but I wanna sort this part out first before I get on to that:)
A=zeros(2)
selected=0;
flag=-3
for r=1:2
for c=1:2
A(r,c)==-2;
end
end
while % any of the elements in A are equal to -2
while selected~=-1
selectRow=input('Which row is the cell you would like to access on? ');
selectCol=input('Which column is the cell you would like to access on? ');
selectFlag=input('Would you like to put a flag in this cell? ','s');
if selectRow<=2 && selectRow>=1 && selectCol<=2 && selectCol>=1
while strcmp(selectFlag, 'yes') || strcmp(selectFlag, 'no')
if strcmp(selectFlag, 'yes')
A(selectRow,selectCol)=flag;
disp(A);
elseif strcmp(selectFlag, 'no')
selected=mineBoard(selectRow,selectCol);
A(selectRow,selectCol)=selected;
disp(A);
end
end
end
end
fprintf('You have hit a mine. Please restart.\n');
end
fprintf('Congrats! You have won!');
There are multiple ways to know if an entry of A is equal to -2 and how to interact with the location of all those entries.
The any function
As suggested by #etmuse and #Wolfie in the comments, the any function may be best here. Notice in the documentation that more advanced options are available for versions R2018b and later.
% MATLAB R2017a
rng(8675309) % For reproducibility (ensure some -2 appear)
A = randi([-4 0],4) % Generate example matrix
any(A == -2,1) % Test columns of A
any(A == -2,2) % Test rows of A
Logical Index
% Use a logical index
idx = (A == -2)
Indices
It is a bit trickier to use the indices.
% Use the indices directly.
ind = find(A==-2)
Notice this gives you the indices if the array A were converted to vector form.
A(:) % Force column vector
reshape(A(:),4,4)' % Reshape into matrix
Disclosure: If #etmuse or #Wolfie post answer with any function, will remove that from my answer or make this community wiki. It was their idea.

Looping through columns and rows without using Indexing in matlab

I'm fairly new to matlab and I'm currently working on MATLAB to create a loop that will go through each column and each row and then increment A and B as it goes. I know that there's indexing which you can do but I'd like to learn how to do it step by step. I've come up with the pseudo code for it but I'm struggling with the actual syntax in MATLAB to be able to do it.
Pseudocode:
For columns i 1-300;
Increment A
For rows j 1-4
Increment B
End
End
My actual code that I've been trying to get to work is:
%testmatrix = 4:300 Already defined earlier as a 4 row and 300 column matrix
for i = testmatrix (:,300)
for j = testmatrix (4,:)
B=B+1
end
A=A+1
end
I'm not 100% sure how I'm supposed to format the code so it'll read testmatrix(1,1) all the way through to testmatrix (4,300).
Any help would be greatly appreciated!
You could let it run through the first row to get the right column, then through that column. But you can't feed your running value from the matrix:
[rows cols] = size(testmatrix); %// rows=4, cols=300
for i = 1:cols
for j = 1:rows
temp = testmatrix (j,i); %// contains the element of your matrix at (j,i)
B=B+1;
end
A=A+1;
end
The semicolons ; suppress the output to the command line. Remove them if you want to output A and B at each step.
Here, temp will cycle through the elements (1,1) through (4,300) and you can do whatever you want with them. Note that this is generally an inefficient way to do most things. Matlab supports greatly efficient vectorized calculations, which you should use. But unless I know what exactly you're trying to achieve, I can't really help you with that. (If all you want is A and B's final values, it's as easy as A=A+cols;B=B+cols*rows;.)

Efficient way to restrict matrix within specified values

I am working on a big Matlab testbench with thousands of lines of code, and I am trying to optimize the most time-consuming routines, determined via the profiler in Matlab.
I noticed that one of those most time-consuming operations is the following:
list = list((list(:,1) >= condxMin) & (list(:,1) <= condxMax) & (list(:,2) >= condyMin) & (list(:,2) <= condyMax),:);
Concretely, I have a big list of coordinates (50000 x 2 at least) and I want to restrict the values of this list so as to keep only the points that verify both of these conditions :
list(:,1) must be within [condxMin, condxMax] and list(:2) within [condyMin condyMax].
I was wondering if there was a more efficient way to do it, considering that this line of code is already vectorized.
Also, I am wondering if Matlab does a short-circuiting or not. If it doesn't, then I don't think there is a way to do it without breaking the vectorization and do it with a while loop, where I would write instead something like this:
j=1;
for i=1:size(list,1)
if(cond1 && cond2 && cond3 && cond4)
newlist(j,1:2) = list(i,1:2);
j=j+1;
end
end
Thank you in advance for your answer :)
Looks like the original vectorized version is the fastest way I can find, barring any really clever ideas. Matlab does do short circuiting, but not for matrices. The loop implementation you you showed would be very slow, since you're not pre-allocating (nor are you able to pre-allocate the full matrix).
I tried a couple of variations on this, including a for loop which used a short circuited && to determine whether the index was bad or not, but no such luck. On the plus side, the vectorized version you've got runs at 0.21s for a 5 million element coordinate list.

How to speed up array concatenation?

Instead of concatening results to this, Is there other way to do the following, I mean the loop will persist but vector=[vector,sum(othervector)]; can be gotten in any other way?
vector=[];
while a - b ~= 0
othervector = sum(something') %returns a vector like [ 1 ; 3 ]
vector=[vector,sum(othervector)];
...
end
vector=vector./100
Well, this really depends on what you are trying to do. Starting from this code, you might need to think about the actions you are doing and if you can change that behavior. Since the snippet of code you present shows little dependencies (i.e. how are a, b, something and vector related), I think we can only present vague solutions.
I suspect you want to get rid of the code to circumvent the effect of constantly moving the array around by concatenating your new results into it.
First of all, just make sure that the slowest portion of your application is caused by this. Take a look at the Matlab profiler. If that portion of your code is not a major time hog, don't bother spending a lot of time on improving it (and just say to mlint to ignore that line of code).
If you can analyse your code enough to ensure that you have a constant number of iterations, you can preallocate your variables and prevent any performance penalty (i.e. write a for loop in the worst case, or better yet really vectorized code). Or if you can `factor out' some variables, this might help also (move any loop invariants outside of the loop). So that might look something like this:
vector = zeros(1,100);
while a - b ~= 0
othervector = sum(something);
vector(iIteration) = sum(othervector);
iIteration = iIteration + 1;
end
If the nature of your code doesn't allow this (e.g. you are iterating to attain convergence; in that case, beware of checking equality of doubles: always include a tolerance), there are some tricks you can perform to improve performance, but most of them are just rules of thumb or trying to make the best of a bad situation. In this last case, you might add some maintenance code to get slightly better performance (but what you gain in time consumption, you lose in memory usage).
Let's say, you expect the code to run 100*n iterations most of the time, you might try to do something like this:
iIteration = 0;
expectedIterations = 100;
vector = [];
while a - b ~= 0
if mod(iIteration,expectedIterations) == 0
vector = [vector zeros(1,expectedIterations)];
end
iIteration = iIteration + 1;
vector(iIteration) = sum(sum(something));
...
end
vector = vector(1:iIteration); % throw away uninitialized
vector = vector/100;
It might not look pretty, but instead of resizing the array every iteration, the array only gets resized every 100th iteration. I haven't run this piece of code, but I've used very similar code in a former project.
If you want to optimize for speed, you should preallocate the vector and have a counter for the index as #Egon answered already.
If you just want to have a different way of writing vector=[vector,sum(othervector)];, you could use vector(end + 1) = sum(othervector); instead.