using logical indexing to find events

2 views (last 30 days)
William Rose
William Rose on 16 Dec 2021
Commented: Mathieu NOE on 17 Dec 2021
I have three vectors of the same length: t, x, y. I also have tevent, whose elements are a subset of the elements in t. Can I use logical indexing, without a for loop, to find all the elements of x and y whose times are the times in tevent?
Example:
t=0:0.01:10; x=sin(2*pi*t)+t/10; y=sin(2*pi*t+pi/4);
tevent=[5.3,3.2,8.7,2,0.9];
%xevent=x(t==tevent)); %I wish this would work, but it causes an error.
%Next line is not practical when tevent has many elements,
%and is impossible, if length(tevent) is not known in advance.
xevent=x(t==tevent(1)|t==tevent(2)|t==tevent(3)|t==tevent(4)|t==tevent(5));
yevent=y(t==tevent(1)|t==tevent(2)|t==tevent(3)|t==tevent(4)|t==tevent(5));
%for loop works, but seems ugly
xe2=zeros(size(tevent)); ye2=xe2;
for i=1:length(tevent)
xe2(i)=x(t==tevent(i));
ye2(i)=y(t==tevent(i));
end
plot(x,y,'-r',xevent,yevent,'bx',xe2,ye2,'g+');
There must be a better way than what I did above.
Another thing: certain event times do not get found by the search above. I guess this is a rounding thing. For example, the line below should find two values in the vector t, but it fails to find the element t=5.4.
fprintf('Find and print two values: %.1f, %.1f.\n',t(t==5.3),t(t==5.4));
Find and print two values: 5.3, .
A workaround is
fprintf('Find and print two values: %.1f, %.1f.\n',t(abs(t-5.3)<1e-6),t(abs(t-5.4)<1e-6));
Find and print two values: 5.3, 5.4.
Thanks in advance.

Accepted Answer

Mathieu NOE
Mathieu NOE on 16 Dec 2021
hello
there is a very simple answer using interp1
t=0:0.01:10; x=sin(2*pi*t)+t/10; y=sin(2*pi*t+pi/4);
tevent=[5.3,3.2,8.7,2,0.9];
xevent=interp1(t,x,tevent);
yevent=interp1(t,y,tevent);
plot(x,y,'-r',xevent,yevent,'bd');

More Answers (2)

Steven Lord
Steven Lord on 16 Dec 2021
Use ismembertol (to avoid floating-point issues) or ismember (if your time data contains exactly represtentable times.)
t=0:0.01:10;
x=sin(2*pi*t)+t/10;
y=sin(2*pi*t+pi/4);
tevent=[5.3,3.2,8.7,2,0.9];
eventLocations = ismembertol(t, tevent);
tsort = sort(tevent);
times = [t(eventLocations); tsort]
times = 2×5
0.9000 2.0000 3.2000 5.3000 8.7000 0.9000 2.0000 3.2000 5.3000 8.7000
checkX = [x(eventLocations); sin(2*pi*tsort)+(tsort/10)]
checkX = 2×5
-0.4978 0.2000 1.2711 1.4811 -0.0811 -0.4978 0.2000 1.2711 1.4811 -0.0811
checkY = [y(eventLocations); sin(2*pi*tsort+pi/4)]
checkY = 2×5
0.1564 0.7071 0.8910 0.4540 -0.8910 0.1564 0.7071 0.8910 0.4540 -0.8910
  1 Comment
William Rose
William Rose on 16 Dec 2021
@Steven Lord, thank you for telling me about ismember() and ismembertol().
I would accept your answer too, if it were possible to accept more than one.

Sign in to comment.


William Rose
William Rose on 16 Dec 2021
@Mathieu NOE, Thank you very much!

Community Treasure Hunt

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

Start Hunting!

Translated by