I have 2 data vectors with corresponding time vectors. This data is sampled nearly simultaneously but they have slightly different timestamps (from machine precision transmission delays etc.). One or both of the data vectors experience occasional data losses & occasional double samples due to telemetry issues.
I want to match up the data arrays to where their times match to perform some math operations between them. Essentially remove points from y1
& y2
where they do not have corresponding times x1
& x2
(within about 1/2 of the sample rate to be considered a match).
Note I do not want to interpolate y1
& y2
%Sample time stamps: Real ones are much faster and not as neat.
x1 = [1 2 3 4 5 5.1 6 7 8 10 ]; %note double sample at ~5.
x2 = [.9 4.9 5.9 6.9 8.1 9.1 10.1]; %Slightly different times.
%Sample data: y is basically y1+1 if no data was missing
y1 = [1 2 3 4 5 5 6 7 8 10];
y2 = [2 6 7 8 9 10 11];
So the result should look like:
y1_m = [1 5 6 7 8 10];
y2_m = [2 6 7 8 9 11];
What I have so far: I used interp1
to find the closest time points between the 2 time arrays. Then got the time delta between them like this:
>> idx = interp1(x2,1:numel(x2),x1,'nearest','extrap')
idx =
1 1 2 2 2 2 3 4 5 7
>> xDelta = abs(x2(idx) - x1)
xDelta =
0.1000 1.1000 1.9000 0.9000 0.1000 0.2000 0.1000 0.1000 0.1000 0.1000
Now what I think I need to do is for each unique idx
find the min xDelta
and that should get me all the matching points. However, I haven't come up with a clever way of doing that... It seems like accumarray
should be useful here but so far I failed at using it.
Here is a solution based on @Cris Luengo's comment on the original question.
It uses a sortrows
& unique
to get the lowest time error for each pairing of data points.
%Sample time stamps: Real ones are much faster and not as neat.
x1 = [1 2 3 4 5 5.1 6 7 8 10 ]; %note double sample at ~5.
x2 = [.9 4.9 5.9 6.9 8.1 9.1 10.1]; %Slightly different times.
%Sample data: y is basically y1+1 if no data was missing
y1 = [1 2 3 4 5 5 6 7 8 10];
y2 = [2 6 7 8 9 10 11];
%Find the nearest match
idx = interp1(x2,1:numel(x2),x1,'nearest','extrap');
xDiff = abs(x2(idx) - x1);
% Combine the matched indices & the deltas together & sort by rows.
%So lowest delta for a given index is first.
[A, idx1] = sortrows([idx(:) xDiff(:)]);
[idx2, uidx] = unique(A(:,1),'first');
idx1 = idx1(uidx); %resort idx1
%output
y1_m = y1(idx1)
y2_m = y2(idx2)
y1_m =
1 5 6 7 8 10
y2_m =
2 6 7 8 9 11