While using the isnan(x) operator, I notice that the output is an array with 0s and 1s corresponding whether the element is NaN or not.
The logical way to filter out NaN elements would be x(find(~isnan(x))), as find() returns the indices. As a suprise to me, x(~isnan(x)) also gives the same result.
On checking, ~isnan(x) is just an array of 1s and 0s, and for the simple case of x = rand(10,1), I get all(~isnan(x) == ones(10, 1)) as true. But when I run x(ones(10, 1)), I get an array with just the first element of x repeated 10 times, as expected.
What am I missing here?
MATLAB uses multiple type of indices.
isnan returns logical indices. That is, a matrix or vector of size x where it is 1 if that element is nan. The output is logical "binary" variable
find looks for any element that is not 0 and gives you its index. The output are integers.
As such, both outputs can be used as indices so they will the same result. That being said, if you don't need the actual indices (which you don't in your example above), don't use it. find is slow and redundant in the case above.
Now if you create the arrays of 1s like you did above, it treats it as an index (like find) so it returns the value of the first element 10 times. The reason is that the functions ones does not return a logical variable but actual numbers (real). If you substitute ones with true or convert the results into binary first, it will be treat it as logical indices.
Related
I have a 2D array PointAndTangent of dimension 8500 x 5. The data is row-wise with 8500 data rows and 5 data values for each row. I need to extract the row index of an element in 4th column when this condition is met, for any s:
abs(PointAndTangent[:,3] - s) <= 0.005
I just need the row index of the first match for the above condition. I tried using the following:
index = np.all([[abs(s - PointAndTangent[:, 3])<= 0.005], [abs(s - PointAndTangent[:, 3]) <= 0.005]], axis=0)
i = int(np.where(np.squeeze(index))[0])
which doesn't work. I get the follwing error:
i = int(np.where(np.squeeze(index))[0])
TypeError: only size-1 arrays can be converted to Python scalars
I am not so proficient with NumPy in Python. Any suggestions would be great. I am trying to avoid using for loop as this is small part of a huge simulation that I am trying.
Thanks!
Possible Solution
I used the following
idx = (np.abs(PointAndTangent[:,3] - s)).argmin()
It seems to work. It returns the row index of the nearest value to s in the 4th column.
You were almost there. np.where is one of the most abused functions in numpy. Half the time, you really want np.nonzero, and the other half, you want to use the boolean mask directly. In your case, you want np.flatnonzero or np.argmax:
mask = abs(PointAndTangent[:,3] - s) <= 0.005
mask is a 1D array with ones where the condition is met, and zeros elsewhere. You can get the indices of all the ones with flatnonzero and select the first one:
index = np.flatnonzero(mask)[0]
Alternatively, you can select the first one directly with argmax:
index = np.argmax(mask)
The solutions behave differently in the case when there are no rows meeting your condition. Three former does indexing, so will raise an error. The latter will return zero, which can also be a real result.
Both can be written as a one-liner by replacing mask with the expression that was assigned to it.
I have an array in which the first two columns are zero for all entries. The array has non-zero values for some number of columns and then zeros in the rest. I wish to find the column that has the final non-zero (or first zero) entry that is not column 1 or 2, for plotting. I have tried
find(b(i,:)==0,1)
which of course returns 1.
I have tried
find(b(i,:)~=0,1)
which I thought would work, but bizarrely returns '2'. I thought that find(b(i,:)~=0,1, 'last') might work instead, which I have seen being suggested as a MATLAB command on various Stack Overflow responses, however I still get '2'!
Any help would be much appreciated.
You need the second output argument of find which represents the column subscript. i.e.
[~, cfirst] = find(b,1); %to find the column subscript of the first non-zero value
[~, clast] = find(b,1,'last'); %to find the column subscript of the last non-zero value
I need help to speed up this function I created to remove NaN elements in a cell array.
To explain better my function with an example. Let's suppose we have a cell array of I have a cell array on the form indx{ii} where each ii is an array of size 1xNii (this means the arrays have different size) with NaN elements on it.
datawithNaN{1}=[1,4,8,6];
datawithNaN{2}=[4,6,2];
datawithNaN{3}=[9,8,NaN];
datawithNaN{4}=[3,NaN,NaN];
datawithNaN{5}=[NaN,NaN,NaN,NaN];
What I want the function function to do is remove all NaN elements in the cell array. So the answer for the example should be:
datawithoutNaN{1}=[1,4,8,6];
datawithoutNaN{2}=[4,6,2];
datawithoutNaN{3}=[9,8];
datawithoutNaN{4}=[3];
datawithoutNaN{5}=[];
So far I have written a function that gives me the result I want but it takes too much time specially when working with big cell arrays or big arrays inside the cell array.
My function is:
function result = rmNaN(datawithNaN)
[row_cell, col_cell] = size(datawithNaN);
result = cell(row_cell, col_cell);
for i=1:row_cell
for j=1:col_cell
[row,col]=size(datawithNaN{i,j});
if col>row
datawithNaN{i,j}=datawithNaN{i,j}';
[row,~]=size(datawithNaN{i,j});
end
for k=1:row
if ~isnan(datawithNaN{i,j}(k))
result{i,j}(k) = datawithNaN{i,j}(k);
else
continue
end
end
end
end
You can easily accomplish this with cellfun.
datawithoutNaN = cellfun(#(x)x(~isnan(x)), datawithNaN, 'uniform', 0);
This goes through each element of the cell array, uses isnan to determine which elements in the array are NaN and yields a logical array the same size as x where it is true where it is a NaN and false otherwise. It then negates this and uses it as a logical index to grab only the non-Nan values and return them. The 'uniform' input ensures that the result is also a cell array.
Say I have a vector, for example, x <- 1:10, then x[0] returns a zero-length vector of the same class as x, here integer(0).
I was wondering if there is a reason behind that choice, as opposed to throwing an error, or returning NA as x[11] would? Also, if you can think of a situation where having x[0] return integer(0) is useful, thank you for including it in your answer.
As seen in ?"["
NA and zero values are allowed: rows of an index matrix containing a
zero are ignored, whereas rows containing an NA produce an NA in the
result.
So an index of 0 just gets ignored. We can see this in the following
x <- 1:10
x[c(1, 3, 0, 5, 0)]
#[1] 1 3 5
So if the only index we give it is 0 then the appropriate response is to return an empty vector.
My crack at it as I am not a programmer and certainly do not contribute to R source. I think it may be because you need some sort of place holder to state that something occurred here but nothing was returned. This becomes more apparent with things like tables and split. For instance when you make a table of values and say there are zero of that cell you need to hold that that cell made from a string in a vector has no values. it would not be a appropriate to have x[0]==0 as it's not the numeric value of zero but the absence of any value.
So in the following splits we need a place holder and integer(0) holds the place of no values returned which is not the same as 0. Notice for the second one it returns numeric(0) which is still a place holder stating it was numeric place holder.
with(mtcars, split(as.integer(gear), list(cyl, am, carb)))
with(mtcars, split(gear, list(cyl, am, carb)))
So in a way my x[FALSE] retort is true in that it holds the place of the non existent zero spot in the vector.
All right this balonga I just spewed is true until someone disputes it and tears it down.
PS page 19 of this guide (LINK) state that integer() and integer(0) are empty integer.
Related SO post: How to catch integer(0)?
Since the array indices are 1-based, index 0 has no meaning. The value is ignored as a vector index.
Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?
The way I intend to use it is to check whether an element index in one matrix is equal to the values stored in another array (where the stored values are the indices of the elements which meet a certain criteria).
So, if the indices of the elements which meet the criteria are stored in the matrix below:
criteriacheck = [3 5 6 8 20];
Going through the main array (called array) and checking if the index matches:
for i = 1:numel(array)
if i == 'Any value stored in criteriacheck'
%# "Do this"
end
end
Does anyone have an idea of how I might go about this?
The excellent answer previously given by #woodchips applies here as well:
Many ways to do this. ismember is the first that comes to mind, since it is a set membership action you wish to take. Thus
X = primes(20);
ismember([15 17],X)
ans =
0 1
Since 15 is not prime, but 17 is, ismember has done its job well here.
Of course, find (or any) will also work. But these are not vectorized in the sense that ismember was. We can test to see if 15 is in the set represented by X, but to test both of those numbers will take a loop, or successive tests.
~isempty(find(X == 15))
~isempty(find(X == 17))
or,
any(X == 15)
any(X == 17)
Finally, I would point out that tests for exact values are dangerous if the numbers may be true floats. Tests against integer values as I have shown are easy. But tests against floating point numbers should usually employ a tolerance.
tol = 10*eps;
any(abs(X - 3.1415926535897932384) <= tol)
you could use the find command
if (~isempty(find(criteriacheck == i)))
% do something
end
Note: Although this answer doesn't address the question in the title, it does address a more fundamental issue with how you are designing your for loop (the solution of which negates having to do what you are asking in the title). ;)
Based on the for loop you've written, your array criteriacheck appears to be a set of indices into array, and for each of these indexed elements you want to do some computation. If this is so, here's an alternative way for you to design your for loop:
for i = criteriacheck
%# Do something with array(i)
end
This will loop over all the values in criteriacheck, setting i to each subsequent value (i.e. 3, 5, 6, 8, and 20 in your example). This is more compact and efficient than looping over each element of array and checking if the index is in criteriacheck.
NOTE: As Jonas points out, you want to make sure criteriacheck is a row vector for the for loop to function properly. You can form any matrix into a row vector by following it with the (:)' syntax, which reshapes it into a column vector and then transposes it into a row vector:
for i = criteriacheck(:)'
...
The original question "Can anyone tell me if there is a way (in MATLAB) to check whether a certain value is equal to any of the values stored within another array?" can be solved without any loop.
Just use the setdiff function.
I think the INTERSECT function is what you are looking for.
C = intersect(A,B) returns the values common to both A and B. The
values of C are in sorted order.
http://www.mathworks.de/de/help/matlab/ref/intersect.html
The question if i == 'Any value stored in criteriacheck can also be answered this way if you consider i a trivial matrix. However, you are proably better off with any(i==criteriacheck)