Get the index of the first element in an array that meets the specified condition - find

For example, I have an array data = 0 0 0 0 0 0 1 1 1. I want to get the index of the first non-zero element in the array.

Use the function ifirstHit. For example:
data = 0 0 0 0 0 0 1 1 1
ifirstHit(ne, data, 0)
Output: 6

Find first 1
data.find(1)
Find first non-zero element
data.find(data[data != 0].first())

Related

How can I assign the values using index matrix in Matlab?

I'm working in Matlab and I have the following problem:
I have a 2x4 matrix A
A = 0 0 0 0
0 0 0 0
and index matrix
index = 1 2
2 3
each row of index matrix indicates the location I want to assign in A. What should I do to make A be
A = 1 1 0 0
0 1 1 0
Another Example: if index is
index = 1 3
2 4
then
A = 1 0 1 0
0 1 0 1
Thanks!
You can do this using linear indexing and implicit expansion:
A((index-1).*size(A,1)+(1:size(index,1)).') = 1;

Obtaining the position of a random 1 in an array of 0's in MATLAB

I have a matrix which is initialized as follows:
stateAndAction = zeros(11, 4);
Over time the matrix will be updated so that at a given index, there will be a one. So at any given time we could have something that looks like this
1 1 0 1
1 0 0 0
0 1 0 0
0 0 1 0
0 1 0 0
0 0 0 1
1 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
How do I find a random row and column with a one in it?
This is the function signature I had in mind:
[random_row_index, random_column_index] = findRandom(stateAndAction)
You can find the position of non-zero elements with find, select a random element and convert index to row/column position in the array:
function [random_row_index, random_column_index] = findRandom(stateAndAction)
ids = find(stateAndAction==1);
random = randi([1,numel(ids)],1);
id=ids(random);
[random_row_index, random_column_index] = ind2sub(size(stateAndAction),id);
end

Create a vector that holds the index of all the columns which has non-zero values based on a condition

I have a matrix filled with zeros and ones and I need to count the number of ones in each row. Then I need to know which row's count exceeds or equal a specific limit (any number, for example 3). After that foreach row in these rows I need to create a vector that holds the index of all the columns which has non-zero values in that row and in all the rows above it and below it till it reach a row with zero count.
Example:
data contains the data below:
0 0 0 0 0 0 0
0 0 0 1 1 0 0
0 1 0 0 1 0 1
0 0 0 0 0 0 0
0 1 0 0 0 0 0
0 1 1 1 0 0 0
0 0 1 0 0 0 0
0 0 0 0 0 0 0
The output should be if the limit is 3:
Row 3: col 4 5 2 5 7
Row 6: col 2 2 3 4 3
I already read the data and I counted the ones in the code below:
load('data');
mat(isnan(mat)) = 0;
[rows,cols,vals] = find(mat~= 0);
unqRows=unique(rows);
countElinRows=histc(rows,unqRows);
Edit for clarification as requested by commentators:
If the third row of the given sample input array becomes [0 1 0 0 0 0 1], then we must only have this output -
Row 6: col 2 2 3 4 3
Assuming A as the input array, see if this works for you -
[sc1,sr1] = find(A') %//'# row and col indices for sorted rows
s_a1 = sum(A,2) %// sum input array along cols
bounds = find(s_a1==0) %// find bounds/gropus delimited by all zero rows
bounds = unique([1 ; bounds ; size(A,1)]) %// account for non all zero
%// starting and ending rows
cumsum1 = cumsum(s_a1==0) + double(sum(A(1,:))~=0) %// label groups
valid_groups = accumarray(cumsum1, s_a1, [], #max)>=3 %// valid groups
out = arrayfun(#(k1) sc1(sr1>=bounds(k1) & sr1<=bounds(k1+1)),...
1:numel(bounds)-1,'un',0) %// find all indices within each group
out = out(valid_groups) %// select only the valid groups for the final output
Visualized output with celldisp(out).
Apologies for strange code, but it's the best I could come up with
[I1,~]=find(sum(mat,2)>=3)
[I2,~]=find(sum(mat,2)==0)
[~,CM]=find(diff(mod(sum(bsxfun(#le,I1,I2.')),2))~=0)
[I,J]=arrayfun(#(t)find(mat(I2(CM(t)):I2(CM(t)+1),:)>0),1:length(CM),'UniformOutput',false)
[~,w]=cellfun(#sort,I,'UniformOutput',false);
J=arrayfun(#(t) J{t}(w{t}).',1:length(J),'UniformOutput',false)
celldisp(J)
This code does feel pretty overcomplicated.
I have tested it on a few cases and it seems to be fine, but it's hard to know for certain.

howto find out if a vector contains only one 1 and other are 0? or how to check if every entry is the same?

howto find out if a vector contains only one 1 and other are 0? or how to check if every entry is the same?
e.g. i need to check if a vector contains zeros except only one 1 like:
(0 0 0 0 1 0 0 0 0) -> true
(0 0 0 0 0 0 0 0 1) -> true
(0 0 0 0 2 0 0 0 0) -> false
(0 0 1 0 1 0 0 0 0) -> false
You can use logical indexing, assuming your vector is v: numel(v(v==1)) returns the number of elements equal to 1 in your vector.
In the same way, if you want to check if every value is the same you can use: numel(unique(v)) which returns the number of unique entries of v.
A slightly different solution:
v = [0 0 0 0 1 0 0 0 0];
TF = sum(v==1)==1 %# returns TRUE
This is especially useful if you want to apply it to all rows of a matrix:
M = [
0 0 0 0 1 0 0 0 0 ;
0 0 0 0 0 0 0 0 1 ;
0 0 0 0 2 0 0 0 0 ;
0 0 1 0 1 0 0 0 0
];
TF = sum(M==1,2)==1
The result:
>> TF
TF =
1
1
0
0
The check for only zeroes could be achieved by extracting all unique elements from your variable:
u = unique (v)
You can then compare the result to zero and voila.
To check for a non-zero element, use the find function. If it finds only one index and that entry is one, your desired result is true. Otherwise it's false.
function bool = oneone(vector)
num = find(vector);
bool = isscalar(num) && vector(num)==1;
end
For all same entries, the diff function calculates the difference of subsequent elements. If any of the results are non-zero, your desired result is false.
function bool = allsame(vector)
d = diff(vector);
bool = ~any(d);
end

Using find function on columns and rows in matlab

I am having some problems with the find function in MATLAB. I have a matrix consisting of zeros and ones (representing the geometry of a structural element), where material is present when the matrix element = 1, and where no material is present when the matrix element = 0. The matrix may have the general form shown below (it will update as the geometry is changed, but that isn't too important).
Geometry = [0 0 0 0 0 0 0 0 0 0;
0 0 1 0 1 0 1 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 0 0 0;
0 0 0 0 0 0 0 1 0 0;
0 0 0 0 0 0 0 0 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 1 1 1 0 1 0 0;
0 0 0 0 0 0 0 0 0 0;]
I'm trying to find the the rows and columns that are not continuously connected (i.e. where the row and columns are not all equal to 1 between the outer extents of the row or column) and then update them so they are all connected. I.e. the matrix above becomes:
Geometry = [0 0 0 0 0 0 0 0 0 0;
0 0 1 1 1 1 1 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 0 0 0 0 1 0 0;
0 0 1 1 1 1 1 1 0 0;
0 0 0 0 0 0 0 0 0 0;]
The problem I am having is I want to be able to find the indices of the first and last element that is equal to 1 in each row (and column), which will then be used to update the geoemtry matrix.
Ideally, I want to represent these in vectors, so going across the columns, find the row number of the first element equal to 1 and store this in a vector called rowfirst.
I.e.:
rowfirst = zeros(1,numcols)
for i = 1:numcols % Going across the columns
rowfirst(i) = find(Geometry(i,1) == 1, 1,'first')
% Store values in vector called rowfirst
end
and the repeat this for the columns and to find the last elements in each row.
For some reason, I can't get the values to store properly in the vector, does anyone have an idea of where I'm going wrong?
Thanks in advance. Please let me know if that isn't clear, as I may not have explained the problem very well.
0) bwmorph(Geometry,'close') dose it all in one line. If the holes may be bigger, try bwmorph(Geometry,'close',Inf).
Regarding your attempt:
1) It should be Geometry(i,:) instead of Geometry(i,1).
2) Your real problem here is empty matrices. Actually, what do you want rowfirst(i) to be if there are no 1s in the i'th row?
Ok, I can spot two mistakes:
You should use an array as the first argument of find. So, if you want to find the row number of the first element of each column, then you should use find(Geometry(:, i), 1, 'first').
Find returns an empty array if the column contains only zeros. You should handle this case and decide what number you want to put into rownumber (e.g. you can put -1, to indicate that the corresponding column contains no non-zero elements).
Following the above, you can try this:
for i = 1:numcols
tmp = find(Geometry(:, i), 1, 'first');
if(tmp)
rowfirst(i) = tmp;
else
rowfirst(i) = -1;
end;
end;
I'm pretty sure there's a more efficient way of doing this, but if you replace your call to find with this, it should work ok:
find(Geometry(i,:), 1,'first')
(otherwise you're just looking at the first cell of the ith row. And the == 1 is useless, since find already returns only non-zero elements, and your matrix is binary)
Use the AccumArray() function to find the min and max col (row) number.
Imagine finding the last (first) row in each column that contains a NaN.
a = [1 nan nan nan ;
2 2 3 4;
3 nan 3 3;
4 nan 4 4]
This code gets the row indices for the last NaN in each column.
[row,col] = find(isnan(a))
accumarray(col,row,[],#max)
This code gets the row indices for the first NaN in each column.
[row,col] = find(isnan(a))
accumarray(col,row,[],#min)
Swap the row and col variables to scan row-wise instead of column-wise.
This answer inspired by Finding value and index of min value in a matrix, grouped by column values