Problem using find function in MATLAB
I have two arrays of data that I am trying to combine. One contains the actual delays from the experiment in the first column (e.g. 0.345, 0.455 ... no more than 3 decimal places), as well as other data from that experiment. Another contains what is effectively a "lookup" list of 0.001 to 0.500 delays in 0.001 increments, as well as other pieces of data. Both datasets are X-by-Y doublings.
What I am trying to do is something like ...
for i = 1:length(actual_latency)
row = find(predicted_data(:,1) == actual_latency(i))
full_set(i,1:4) = [actual_latency(i) other_info(i) predicted_info(row,2) ...
predicted_info(row,3)];
end
... to find the matching line in predicted_data
where the seek latency matches the actual latency. Then I use this to create a merged dataset full_set
.
I figured it would be very simple, but the find function keeps failing, throwing an empty matrix when looking for the actual delay I know in predicted_data(:,1)
(since I double checked while debugging).
Also, if I replace find with a for loop to do the same job, I get a similar error. It doesn't seem systematic - using different sets of participant data invokes it in different places.
Also, in debug mode, if I use find to find a hardcoded value actual_latency
, it doesn't always work. Sometimes yes, sometimes no.
I am really scratching my head over this, so if anyone has any ideas on what might be going on, I would really appreciate it.
a source to share
You will most likely run into a floating point comparison problem if you do the following:
predicted_data(:,1) == actual_latency(i)
Even though your digits only have three decimal places of precision, they can still differ in very small amounts that are not displayed, giving you an empty matrix as FIND cannot get an exact match.
One peculiarity of floating point numbers is that certain numbers cannot be accurately represented because they are not integer powers of 2. This happens with the numbers 0.1 and 0.001. If you re-add or multiply one of these numbers, you might see some unexpected behavior. Amro gave one example in his comment: 0.3
not exactly equal 3*0.1
. This can also be illustrated by creating your search list of delays in two different ways. You can use the normal colon syntax :
vec1 = 0.001:0.001:0.5;
Or you can use LINSPACE :
vec2 = linspace(0.001,0.5,500);
You think these two vectors will be equal to each other, but think again:
>> isequal(vec1,vec2)
ans =
0 %# FALSE!
This is because the two methods create vectors by performing successive additions or multiplications of 0.001 in different ways, while giving slightly different values for some of the elements in the vector. You can learn more about this in this technical solution .
When comparing floating point numbers, you must make your comparisons using some tolerance. For example, this finds the indices of the entries in the search list that are within 0.0001 of your actual delay:
tolerance = 0.0001;
for i = 1:length(actual_latency)
row = find(abs(predicted_data(:,1) - actual_latency(i)) < tolerance);
...
Floating point comparison is also covered in this question.
a source to share