Precision of numbers problem (I think)

4 views (last 30 days)
Phillip
Phillip on 1 Oct 2021
Commented: Phillip on 1 Oct 2021
I have a matrix with 4 columns. I'd like to do something very simple, which is average all numbers in Column 4 given specific numbers in Column 2 but I end up with NaNs for 2 of the 7 means with the code below.
I have a sample "new_data.mat" attached.
This is the Matlab script I'm trying to get to work (rounding alone has not solved the problem):
clear all; clc; close all
alldir = dir(['SS*']);
P = pwd;
for d = 1:size(alldir,1)
PathName = [P, '\', alldir(d).name, '\Behaviour\'];
cd(PathName)
FileName = dir('ID*_PRIM_beh_all.mat');
new_data = cell2mat(struct2cell(load(FileName.name))); % example in my dropbox linked above
phys_diffs = 0:.15:.90;
for k = 1:7
step = phys_diffs(k);
avgdiffRT(k) = mean(new_data(new_data(:, 2) == step, 4));
end
alldiffRT(d, :) = avgdiffRT;
end
If I use the function "round" and take the loop out, i.e. average each of the 7 steps "manually" it works:
rounded = round(new_data(:, 2), 2);
avgRTphysdiff1 = mean(new_data(rounded == 0, 4));
avgRTphysdiff2 = mean(new_data(rounded == .15, 4));
etc
Does somebody have an idea how to get the loop to work?
  1 Comment
Stephen
Stephen on 1 Oct 2021
"Does somebody have an idea how to get the loop to work?"
Do NOT use ROUND. It is not a robust approach, and should be avoided.
Nor should you compare for exact equivalence of floating point numbers, e.g. using EQ or ISMEMBER.
The simple, robust, recommended approach is to compare the absolute difference against a tolerance:
tol = 1e-5; % pick the tolerance to suit your needs.
abs(A-B)<tol

Sign in to comment.

Answers (1)

Konrad
Konrad on 1 Oct 2021
Hi Phillip,
yes, it has to do with precision.
ismember(phys_diffs,new_data(:,2))
% ans =
% 1×7 logical array
% 1 0 1 1 1 1 0
This shows that the 2nd and the last value in phy_diffs (.15 and .9) do not appear in new_data(:,2). (And the mean of nothing is NaN)
But values very close to these two numbers do appear. So what you could do is to round new_data(:,2), e.g. to two digits:
idx = round(new_data(:, 2),2) == step;
avgdiffRT(k) = mean(new_data(idx, 4));
Regards, Konrad
  3 Comments
Phillip
Phillip on 1 Oct 2021
Thank you very much for taking the time to write such a detailed explanation. Very useful!!!

Sign in to comment.

Products


Release

R2021b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by