how to select an interval of certain hours each day within a larger timetable using timerange

Hi, I have a timetable of minute by minute data running over multiple days. I wish to identify the times outside regular business hours (9 am to 5 pm) in order to (later) process that data differently from the rest. How do I do this using the timerange function? In other words, how do I select a timerange within each day, for every day, without selecting any full days? Thanks

 Accepted Answer

The timerange function operates on timetable arrays, so to use it, the data must be in a timetable and the times must be duration arrays.
Use table2timetable for this if the data are not already in a timetable.
This uses table2timetable and duration array conversion —
DT = datetime('26-Mar-2022') + minutes(0:1440*2)'; % Two Days
Data = randn(numel(DT),3); % Create Other Values
T1 = [table(DT) array2table(Data)]
T1 = 2881×4 table
DT Data1 Data2 Data3 ____________________ __________ ________ ________ 26-Mar-2022 00:00:00 -0.6546 -0.31415 2.4173 26-Mar-2022 00:01:00 -0.20845 -0.89936 -2.3631 26-Mar-2022 00:02:00 -0.20717 0.55078 0.25069 26-Mar-2022 00:03:00 1.5701 -0.2149 -0.48116 26-Mar-2022 00:04:00 1.3051 -0.62446 0.89712 26-Mar-2022 00:05:00 -0.0059697 0.10382 0.90953 26-Mar-2022 00:06:00 -0.27235 1.0921 -0.53748 26-Mar-2022 00:07:00 1.5568 0.38122 1.2537 26-Mar-2022 00:08:00 -2.1977 1.0529 -1.6526 26-Mar-2022 00:09:00 1.9246 0.68009 -1.306 26-Mar-2022 00:10:00 -0.12461 0.48482 -1.4169 26-Mar-2022 00:11:00 -0.63642 0.081571 -0.11844 26-Mar-2022 00:12:00 0.92942 0.73651 -0.56618 26-Mar-2022 00:13:00 -0.17877 -0.33336 0.33599 26-Mar-2022 00:14:00 -0.41219 -0.85676 -0.80945 26-Mar-2022 00:15:00 0.13819 -0.17675 2.2606
TT1 = table2timetable(T1);
TT1.DT = duration(hour(TT1.DT),minute(TT1.DT),second(TT1.DT))
TT1 = 2881×3 timetable
DT Data1 Data2 Data3 ________ __________ ________ ________ 00:00:00 -0.6546 -0.31415 2.4173 00:01:00 -0.20845 -0.89936 -2.3631 00:02:00 -0.20717 0.55078 0.25069 00:03:00 1.5701 -0.2149 -0.48116 00:04:00 1.3051 -0.62446 0.89712 00:05:00 -0.0059697 0.10382 0.90953 00:06:00 -0.27235 1.0921 -0.53748 00:07:00 1.5568 0.38122 1.2537 00:08:00 -2.1977 1.0529 -1.6526 00:09:00 1.9246 0.68009 -1.306 00:10:00 -0.12461 0.48482 -1.4169 00:11:00 -0.63642 0.081571 -0.11844 00:12:00 0.92942 0.73651 -0.56618 00:13:00 -0.17877 -0.33336 0.33599 00:14:00 -0.41219 -0.85676 -0.80945 00:15:00 0.13819 -0.17675 2.2606
BusinessHours = timerange(hours(9), hours(17), 'closed'); % 09:00 To 17:00
TT1_BusinessHours = TT1(BusinessHours,:)
TT1_BusinessHours = 962×3 timetable
DT Data1 Data2 Data3 ________ ________ _________ _________ 09:00:00 -1.724 0.11354 -0.20664 09:01:00 -0.74624 -0.22058 -0.041664 09:02:00 1.2126 1.5414 1.0954 09:03:00 1.1506 0.4756 -1.3082 09:04:00 0.67332 0.95748 0.61051 09:05:00 1.5053 -0.35985 -0.13002 09:06:00 0.20755 -0.75411 -0.53651 09:07:00 -0.778 -0.96918 -0.28845 09:08:00 1.6209 -0.91014 0.40509 09:09:00 -0.59304 -0.0521 -0.59109 09:10:00 0.80869 -1.5248 -0.71053 09:11:00 0.84078 -0.055333 -0.36499 09:12:00 -0.96482 -0.62741 -0.49314 09:13:00 2.021 -0.95608 0.4493 09:14:00 0.1844 1.2234 0.14406 09:15:00 1.1104 0.38988 0.90148
OtherHours1 = timerange(hours(0),hours(9),'open'); % Midnight To 09:00
OtherHours2 = timerange(hours(17), hours(24), 'open'); % 17:00 To Midnight
TT1_OtherHours = [TT1(OtherHours1,:); TT1(OtherHours2,:)]
TT1_OtherHours = 1916×3 timetable
DT Data1 Data2 Data3 ________ __________ ________ ________ 00:01:00 -0.20845 -0.89936 -2.3631 00:02:00 -0.20717 0.55078 0.25069 00:03:00 1.5701 -0.2149 -0.48116 00:04:00 1.3051 -0.62446 0.89712 00:05:00 -0.0059697 0.10382 0.90953 00:06:00 -0.27235 1.0921 -0.53748 00:07:00 1.5568 0.38122 1.2537 00:08:00 -2.1977 1.0529 -1.6526 00:09:00 1.9246 0.68009 -1.306 00:10:00 -0.12461 0.48482 -1.4169 00:11:00 -0.63642 0.081571 -0.11844 00:12:00 0.92942 0.73651 -0.56618 00:13:00 -0.17877 -0.33336 0.33599 00:14:00 -0.41219 -0.85676 -0.80945 00:15:00 0.13819 -0.17675 2.2606 00:16:00 0.22279 -1.2399 -0.43212
Using timerange is not as straightforward as I thought it would be, and I had to ‘fractionate’ it to get it to work.
% figure
% plot(TT1_BusinessHours.DT, TT1_BusinessHours.Data1)
% figure
% plot(TT1_OtherHours.DT, TT1_OtherHours.Data1)
.

6 Comments

Yes,I am also surprised there is not a more straightforward method. The data is in a timetable labeled by datetime. So it looks like I will have to take each day's data out one day at a time, do the multistep process above, then put it back in a timetable with datetime row labels? Because it looks like in going from datetime to duration labels the dd-mm-yyyy info is dropped.
That‘s correct.
It might be more straightforward to use the isbetween function. It creates a logical vector, and works with both datetime and duration arrays (according to the documentation) so using the conventions in my code, the two groups would be:
BusinessHours = isbetween(TT1,hours(9),hours(17),'open');
OtherHours = TT1(~BusinessHours,:);
DT = datetime('26-Mar-2022') + minutes(0:1440*2)'; % Two Days
Data = randn(numel(DT),3); % Create Other Values
T1 = [table(DT) array2table(Data)];
TT1 = table2timetable(T1)
TT1 = 2881×3 timetable
DT Data1 Data2 Data3 ____________________ ________ _________ ________ 26-Mar-2022 00:00:00 0.0089 1.0802 0.052403 26-Mar-2022 00:01:00 -0.42752 -0.032435 -2.6591 26-Mar-2022 00:02:00 -0.16621 -0.23301 0.86686 26-Mar-2022 00:03:00 -0.15177 0.26352 -0.01072 26-Mar-2022 00:04:00 0.69538 -1.2334 0.61313 26-Mar-2022 00:05:00 -0.29458 0.12531 -0.31381 26-Mar-2022 00:06:00 -0.43038 -0.97858 1.4499 26-Mar-2022 00:07:00 -1.2165 -0.013836 1.7829 26-Mar-2022 00:08:00 0.51098 0.31623 0.13328 26-Mar-2022 00:09:00 0.47328 0.80642 0.42304 26-Mar-2022 00:10:00 0.94732 0.39715 1.4349 26-Mar-2022 00:11:00 -0.17398 -1.3395 1.1198 26-Mar-2022 00:12:00 1.3644 0.11788 -0.73741 26-Mar-2022 00:13:00 0.85061 0.074006 -1.0366 26-Mar-2022 00:14:00 0.78419 -1.9073 -1.03 26-Mar-2022 00:15:00 -0.91914 -1.0953 0.038323
TT1.DT = duration(hour(TT1.DT),minute(TT1.DT),second(TT1.DT))
TT1 = 2881×3 timetable
DT Data1 Data2 Data3 ________ ________ _________ ________ 00:00:00 0.0089 1.0802 0.052403 00:01:00 -0.42752 -0.032435 -2.6591 00:02:00 -0.16621 -0.23301 0.86686 00:03:00 -0.15177 0.26352 -0.01072 00:04:00 0.69538 -1.2334 0.61313 00:05:00 -0.29458 0.12531 -0.31381 00:06:00 -0.43038 -0.97858 1.4499 00:07:00 -1.2165 -0.013836 1.7829 00:08:00 0.51098 0.31623 0.13328 00:09:00 0.47328 0.80642 0.42304 00:10:00 0.94732 0.39715 1.4349 00:11:00 -0.17398 -1.3395 1.1198 00:12:00 1.3644 0.11788 -0.73741 00:13:00 0.85061 0.074006 -1.0366 00:14:00 0.78419 -1.9073 -1.03 00:15:00 -0.91914 -1.0953 0.038323
BusinessHours = isbetween(TT1.DT,hours(9),hours(17),'open'); % 09:00 To 17:00
TT1_BusinessHours = TT1(BusinessHours,:)
TT1_BusinessHours = 958×3 timetable
DT Data1 Data2 Data3 ________ ________ ________ ________ 09:01:00 0.73257 0.27795 0.13411 09:02:00 0.61368 -2.2987 -0.11546 09:03:00 0.96921 -0.17803 -1.2016 09:04:00 1.0591 -0.25522 0.041641 09:05:00 0.86261 -0.11875 -1.1432 09:06:00 0.19201 -0.57453 -0.98597 09:07:00 0.43657 1.9273 -0.93695 09:08:00 -0.72754 0.38783 0.42892 09:09:00 -0.76209 0.032867 -0.15609 09:10:00 -0.62209 0.10424 -0.97316 09:11:00 -1.6538 1.872 2.4745 09:12:00 -1.1019 0.71403 2.0267 09:13:00 1.3847 -0.21659 0.60601 09:14:00 -1.0233 -1.3663 -0.22932 09:15:00 0.14303 -0.16536 -1.4742 09:16:00 0.015824 -0.24718 -0.46047
TT1_OtherHours = TT1(~BusinessHours,:)
TT1_OtherHours = 1923×3 timetable
DT Data1 Data2 Data3 ________ ________ _________ ________ 00:00:00 0.0089 1.0802 0.052403 00:01:00 -0.42752 -0.032435 -2.6591 00:02:00 -0.16621 -0.23301 0.86686 00:03:00 -0.15177 0.26352 -0.01072 00:04:00 0.69538 -1.2334 0.61313 00:05:00 -0.29458 0.12531 -0.31381 00:06:00 -0.43038 -0.97858 1.4499 00:07:00 -1.2165 -0.013836 1.7829 00:08:00 0.51098 0.31623 0.13328 00:09:00 0.47328 0.80642 0.42304 00:10:00 0.94732 0.39715 1.4349 00:11:00 -0.17398 -1.3395 1.1198 00:12:00 1.3644 0.11788 -0.73741 00:13:00 0.85061 0.074006 -1.0366 00:14:00 0.78419 -1.9073 -1.03 00:15:00 -0.91914 -1.0953 0.038323
T1_BusinessHours = T1(BusinessHours,:)
T1_BusinessHours = 958×4 table
DT Data1 Data2 Data3 ____________________ ________ ________ ________ 26-Mar-2022 09:01:00 0.73257 0.27795 0.13411 26-Mar-2022 09:02:00 0.61368 -2.2987 -0.11546 26-Mar-2022 09:03:00 0.96921 -0.17803 -1.2016 26-Mar-2022 09:04:00 1.0591 -0.25522 0.041641 26-Mar-2022 09:05:00 0.86261 -0.11875 -1.1432 26-Mar-2022 09:06:00 0.19201 -0.57453 -0.98597 26-Mar-2022 09:07:00 0.43657 1.9273 -0.93695 26-Mar-2022 09:08:00 -0.72754 0.38783 0.42892 26-Mar-2022 09:09:00 -0.76209 0.032867 -0.15609 26-Mar-2022 09:10:00 -0.62209 0.10424 -0.97316 26-Mar-2022 09:11:00 -1.6538 1.872 2.4745 26-Mar-2022 09:12:00 -1.1019 0.71403 2.0267 26-Mar-2022 09:13:00 1.3847 -0.21659 0.60601 26-Mar-2022 09:14:00 -1.0233 -1.3663 -0.22932 26-Mar-2022 09:15:00 0.14303 -0.16536 -1.4742 26-Mar-2022 09:16:00 0.015824 -0.24718 -0.46047
T1_OtherHours = T1(~BusinessHours,:)
T1_OtherHours = 1923×4 table
DT Data1 Data2 Data3 ____________________ ________ _________ ________ 26-Mar-2022 00:00:00 0.0089 1.0802 0.052403 26-Mar-2022 00:01:00 -0.42752 -0.032435 -2.6591 26-Mar-2022 00:02:00 -0.16621 -0.23301 0.86686 26-Mar-2022 00:03:00 -0.15177 0.26352 -0.01072 26-Mar-2022 00:04:00 0.69538 -1.2334 0.61313 26-Mar-2022 00:05:00 -0.29458 0.12531 -0.31381 26-Mar-2022 00:06:00 -0.43038 -0.97858 1.4499 26-Mar-2022 00:07:00 -1.2165 -0.013836 1.7829 26-Mar-2022 00:08:00 0.51098 0.31623 0.13328 26-Mar-2022 00:09:00 0.47328 0.80642 0.42304 26-Mar-2022 00:10:00 0.94732 0.39715 1.4349 26-Mar-2022 00:11:00 -0.17398 -1.3395 1.1198 26-Mar-2022 00:12:00 1.3644 0.11788 -0.73741 26-Mar-2022 00:13:00 0.85061 0.074006 -1.0366 26-Mar-2022 00:14:00 0.78419 -1.9073 -1.03 26-Mar-2022 00:15:00 -0.91914 -1.0953 0.038323
So using isbetween is likely more efficient (and much easier to code). Unfortunately, to have it work over multiple days, the time variable must be a duration. However, once it is defined, it can be used with the original table so that may be the best option. That required a bit of experimentation to fully appreciate. It would likely also work on the original timetable prior to converting the time variable to a duration array.
This may be the only way to make it work, so do the time segmentation on the duration array (that can probably be created specifically to use it with isbetween to create the logical vector), and do the rest of the calculations on the original timetable, after applying the isbetween logical vector to it.
.
You put a lot of thought into this on my behalf, and I am grateful. Something like this should work. Kevin
Just tried running your code as is, but get an error message:
DT = datetime('26-Mar-2022') + minutes(0:1440*2)'; % Two Days
Data = randn(numel(DT),3); % Create Other Values
T1 = [table(DT) array2table(Data)];
TT1 = table2timetable(T1)
TT1.DT = duration(hour(TT1.DT),minute(TT1.DT),second(TT1.DT))
BusinessHours = isbetween(TT1.DT,hours(9),hours(17),'open'); % 09:00 To 17:00
TT1_BusinessHours = TT1(BusinessHours,:)
TT1_OtherHours = TT1(~BusinessHours,:)
"Unable to use a value of type 'datetime' as an index.
Error in untitled9 (line 23)
TT1.DT = duration(hour(TT1.DT),minute(TT1.DT),second(TT1.DT))"
In MATLAB, indices must be integers greater than 0 or logical values.
I note that you are using R2019a and I (and the online Run feature here) are using R2022a. There very well could be version differences, however that line:
TT1.DT = duration(hour(TT1.DT),minute(TT1.DT),second(TT1.DT))
simply converts ‘TT1.DT’ into a duration array by extracting the hour, minute, and second from the datetime array to create it. Looking at the R2019a documentation, the duration and hour (and I assume the others) do not appear to have changed. I am at a loss to explain the inconsistency, or the error.
It runs correctly in my code, and since I can’t reproduce it, I can’t troubleshoot it.
Check to see that the arguments to the duration function are the simple integers it requires for each argument. Then, see if the duration call works with the same vectors. That’s the only approach I can think of to determine what the problem is.
EDIT — (26 Mar 2022 at 21:50)
The only other possibility that I can think of is that you have an ‘hour’, ‘minute’, or ‘second’ array that is overshadowing the MATLAB functions by those names.
Run:
which hour -all
/MATLAB/toolbox/matlab/timefun/hour.m /MATLAB/toolbox/matlab/datatypes/datetime/@datetime/datetime.m % Shadowed datetime method /MATLAB/toolbox/matlab/bigdata/@tall/hour.m % Shadowed tall method /MATLAB/toolbox/parallel/parallel/@codistributed/hour.m % Shadowed codistributed method
and do the same for each of the others. If the first entry in the output of that call is:
hour is a variable.
or something similar, that is the problem. The solution is to re-name the variable to something that makes sense in the context of the code, and does not overshadow any MATLAB functions.
.

Sign in to comment.

More Answers (1)

Do you accept not using function timerange as follows?
T = readtable('date.txt')
T = 18×1 table
Var1 ___________________ 2015-11-08 12:00:00 2015-11-08 13:01:00 2015-11-08 14:02:00 2015-11-08 15:03:00 2015-11-08 17:00:00 2015-11-08 17:00:01 2015-11-08 18:04:00 2015-11-08 19:04:00 2015-11-08 20:05:00 2015-11-08 21:06:00 2015-11-08 22:07:00 2015-11-08 23:08:00 2015-11-09 00:09:00 2015-11-09 02:10:00 2015-11-09 07:10:00 2015-11-09 08:10:00
T.Var1(hour(T.Var1)<9 | hour(T.Var1)>=17 & ~(hour(T.Var1)>=17 & minute(T.Var1)==0 & second(T.Var1)==0))
ans = 11×1 datetime array
2015-11-08 17:00:01 2015-11-08 18:04:00 2015-11-08 19:04:00 2015-11-08 20:05:00 2015-11-08 21:06:00 2015-11-08 22:07:00 2015-11-08 23:08:00 2015-11-09 00:09:00 2015-11-09 02:10:00 2015-11-09 07:10:00 2015-11-09 08:10:00

Categories

Products

Release

R2019a

Community Treasure Hunt

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

Start Hunting!