Find column-count inbetween integers row-wise in matrix (matlab) - matlab

I have a stupid problem, I can't find the answer to ^^.
I have a 100x10000 double matrix containing integers from 1 to 4 and want to find row-wise the column-count between every single integer
My first idea was to use:
storage_ones = cell(100,1);
for n = 1:100;
[row col] = find(matrix(n,:)==1);
storage_ones{n,1} = col;
end
And then substract them in another loop. But with find I get following Answer:
Empty matrix: 1-by-0
Does anybody have an idea how I can solve this problem?
Thanks in advance!!

Your issue is potentially due to one of two things:
Since you're using a double datatype, it is possible that you're encountering floating point errors where the values aren't going to be 1 exactly. If this is the case consider not checking for exact equality and instead check if it is very close to 1 using a small epsilon (here I used 1e-12).
[row, col] = find(abs(matrix(n,:) - 1) < 1e-12);
If you really have an integer datatype, consider using uint8 to store your data rather than double and then you can perform exact comparisons.
matrix = uint8(matrix);
% Then for your comparison
find(matrix(n,:) == 1)
You may just not have any 1's in that column. If find can't find any matches, it returns an empty array.
find([1 2 3] == 4)
% Empty matrix: 1-by-0

Related

Matlab find function throws size difference error when there is no apparent one

My matlab code is attempting to find the indices in a 601 by 1 matrix that correspond to a given value but says the left and right sides have a different number of elements
pH_fine = pH(1):0.01:pH(end);
pH_labvals = [7.72,9.87,7.4,7.63,7.06,6.85,8.29,9.37,11.1];
index_labvals = [];
a = find(pH_fine == 8); %This works perfectly
for i = 1:length(pH_labvals)
index_labvals(i) = find(pH_fine == pH_labvals(i)); %This throws an error
end
Your problem is that the find(pH_fine == pH_labvals(i)) on the right side sometimes doesn't find any match, and returns an empty result for an index, specifically a 1-by-0 row vector. This doesn't match the size of the left side, which is indexing a 1-by-1 element from your vector index_labvals.
You need to check first if the result of find is empty, and decide what you will put in the index vector in that case, like a 0 or NaN. You will also need to deal with find giving you a vector of indices if pH_labvals has the same value repeated. If you simply want to remove repeated values, you could use unique like so:
pH_labvals = unique(pH_labvals, 'stable');
If you're wondering why you're getting an empty result from find, you should read through this post about the perils of floating-point comparison. One possible solution, assuming pH_labvals contains non-repeated values with 2 decimal places of precision, is to first round your pH_fine vector to 2 decimal places:
pH_fine = round(pH(1):0.01:pH(end), 2);
This should allow you to avoid the errors from floating-point comparison.
An alternative approach is to use interp1 for table lookup:
pH = [1,14]; % Not sure what values you use here, it doesn't matter for the example.
pH_fine = pH(1):0.01:pH(end);
pH_labvals = [7.72,9.87,7.4,7.63,7.06,6.85,8.29,9.37,11.1];
index_labvals = interp1(pH_fine,1:numel(pH_fine),pH_labvals,'nearest')
Here, we're finding the nearest index within pH_fine that matches each of the values in pH_labvals. 1:numel(pH_fine) are the indices into pH_fine.
Note that there's no need for a loop, as interp1 will lookup all pH_labvals at once.

logical operation within vector range expression in MATLAB

can I have something like
A=1:10;
A(1:2 && 5:6)=0;
meaning I want to zero out specific ranges within my vector index expression in one line
Is that possible?
And what if I wanted to zero out all the rest like
A(~[1:2]) = 0
What's the way of logical NOT within vector indexing?
Thanks
The following should work:
idx = [1:2,5:6];
A(idx) = 0
If you want to zero the complement of the vector of indices:
idx = [1:2,5:6];
A(~ismembc(1:length(A),idx)) = 0
Where ismembc is a faster, lightweight version of ismember that assumes the array is sorted and non-sparse with no NaN elements. (Credit goes to this question.)
Just do A([1:2 5:6]). I.e., just create a vector of the indices you want to zero out.

MATLAB: changes in vector elements

I have a some vectors of different large sizes and their value is between 0 and 1. I want to save those indices of elements which there would be any changes in decimal. For an small example, let's assume
V=[0.02,0.1,0.4,0.0054,0.05];
Now the ouptput for this should be as
i={2,4,5}
Would you please let me know how it can be done?
As suggested by #Luis Mendo (including his suggestion with removing ~= 0), here the comment as answer. You can use the logarithm function to determine your number of decimals for you.
i = find(diff(floor(log10(V))))+1
Be sure to use floor to have integer values you can compare to 0.
count = arrayfun(#(x) regexp(num2str(x),'\.','split'),V, 'UniformOutput', false)
dp = cell2mat(arrayfun(#(x) length(x{2}),count, 'UniformOutput', false))
find(diff(dp))+1
I did it this way. First I split the numbers and next i find the length of the second term and lastly, I find whether the length is different from its previous..

Finding all rows in a pair of vectors where both entries are non-zero (Octave)

I have a n x 2 matrix in Octave, and I would like to find every row where the matrix(row, 1) and matrix(row, 2) elements are non-zero. I could use a for loop like this:
[nrows, ncols] = size(data);
for i = 1:nrows
if(data(i, 1) ~= 0 && data(i, 2) ~= 0)
% Do something
end
end
The issue with that is that n is about 3 million, and iteration in Octave takes for ever. I feel like there is a way to do it with find, but I haven't been able to figure it out yet.
Anyone have any advice?
Thanks!
You can create use logical indexing:
idx = all(data(:,1:2)~=0, 2);
The resulting vector idx contains 1s in every row where both cells are non-zero and 0 otherwise.
I think in this case (since it is related with zero values) the following also should work
idx=(data(:,1).*data(:,2)~=0)
But #H.Muster's solution is the one that works in all cases, hence a better one.
If performance is the issue: maybe try converting both columns to logical:
useful = and(logical(data(:,1)),logical(data(:,2)))
Then you can again use logical indexing:
filtered = data(useful,:)

How to extract a row of a matrix

In every other language if I have a matrix, if I call a mono-dimensional index, the result will be an array.I don't know why in Matlab if you take a single index of a matrix, you'll get a single element, that's stupid.
Anyway in C:
mat[4][4];
mat[0] is an array.
In Matlab:
mat=[1 2; 3 4];
How do I take the first row of the matrix? mat(1) is 1, not [1 2].
EDIT: There is another problem, I have a problem with this function:
function str= split(string, del)
index=1;
found=0;
str=['' ; ''];
for i=1:length(string)
if string(i)==del
found=1;
index=1;
elseif found==1
str(2,index)=string(i);
index=index+1;
else
str(1,index)=string(i);
index=index+1;
end
end
end
This returns sometimes a matrix and sometimes an array.
For example if I use split('FF','.') I get 'FF' as result, but what if I want to return a matrix? I can't even choose the dimensione of the matrix, in this context a weak typed language is a big disvantage.
You have to say which columns you want. : stands for all indices in a dimension, so to take first row
mat(1,:)
It is not stupid, but useful. If you address a matrix with only one index, it implicitly gets converted to a vector. This gives you the option to use linear indices (see sub2ind).
This will extract the second row
vector = mat(2,:)
And This will extract the second column
vector = mat(:,2)
You can use
vector = mat(end,:)
To extract the last row
Hope this helps you
From Matrix Indexing in MATLAB:
When you index into the matrix A using only one subscript, MATLAB
treats A as if its elements were strung out in a long column vector,
by going down the columns consecutively
I just hope it doesn't look stupid to you anymore (along with the right answers from angainor and Marwan)