Timetables
|
This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production. The reference material consulted while preparing these pages is listed in the section bibliography. |
Written against MATLAB R2026b. GNU Octave 11.3.0 has no timetable type in its core, so every example on this page is not run here: the code was checked line by line against the R2026b documentation and no captured output is shown. Results are described in prose where they follow from the documented behavior.
A timetable is a table that associates a time with each row. Everything that works for tables works for timetables (indexing with (), {} and ., head, sortrows, groupsummary, joins and plots), and in addition timetables provide functions to align, combine, resample and aggregate time-stamped data. They were introduced in R2016b. Use a timetable whenever rows are readings at times, as in the heatflow thermocouple log; use a plain table when rows are unrelated records.
Terminology
-
Row times are the values that label the rows. They are
datetime,durationor (since R2026b) numericdoubleorsinglevalues. The row times are not a table variable: they have their own dimension, namedTimeby default, which is reached with dot notation,TT.Time. -
A timetable is regular when its row times are evenly spaced (by a fixed
durationor by a calendar unit such as a month) and sorted, and irregular otherwise.isregular(TT)tests it. Since R2026b,isregularalso treats row times at the end of every month or quarter as regular. -
TT.Properties.StartTime,TimeStepandSampleRatedescribe a regular timetable. They are empty orNaNwhere they do not apply. -
Resampling puts the data on a new set of times, by interpolation or by copying values. Aggregating combines the values that fall in each time bin, for example a one-minute mean.
-
Time bins are the intervals between consecutive new row times. Each new row time is the left edge of its bin, and the next one is the right edge.
-
A subscript object (
timerange,withtol,labels) selects rows by time rather than by position.
Creating timetables
| Syntax | Meaning |
|---|---|
|
Row times first, which must then be a |
|
Row times given by name; |
|
Regular row times at |
|
Regular row times spaced by |
|
Preallocates a timetable (also with |
|
Converts a table; the first |
|
Converts a numeric array. |
|
Reads a file; the first column of type |
Other conversions are timetable2table(TT) (the row times become a variable) and timeseries2timetable for timeseries objects.
% Not run here: a regular timetable for the first sensor of the plate
Time = datetime(2026,1,15,10,0,0) + minutes(0:4)';
Temperature = [21.5; 21.6; 21.8; NaN; 22.0];
S1 = timetable(Time, Temperature);
% The same data from a time step
S1b = timetable(Temperature, TimeStep=minutes(1)); % duration row times 0 to 4 min
Not run here. S1 has the row times 10:00 to 10:04 on 15 January 2026 and one variable. The call that omits Time creates duration row times starting at 0 minutes, so no calendar date is recorded.
Source: MATLAB documentation: timetable
Reading a timetable from a file
The heatflow scenario logs thermocouple readings to a CSV file with a timestamp, a sensor ID and a temperature, with gaps (illustrative data; the real file is in the scenario’s data folder):
Time,SensorID,Temperature
2026-01-15 10:00:00,S1,21.5
2026-01-15 10:00:30,S2,22.1
2026-01-15 10:01:00,S1,21.6
2026-01-15 10:01:30,S2,
2026-01-15 10:02:00,S1,21.8
2026-01-15 10:02:30,S2,22.4
readtimetable reads such a file. It takes the same options as readtable (including import options from detectImportOptions, setvartype and VariableNamingRule; see Reading and Writing Tabular Data) and makes the first datetime or duration column the row times. Gaps in numeric columns become NaN.
opts = detectImportOptions("data/sensors.csv");
opts = setvartype(opts, "SensorID", "categorical");
sensorLog = readtimetable("data/sensors.csv", opts);
s1 = sensorLog(sensorLog.SensorID == "S1", "Temperature"); % rows of sensor S1 only
s2 = sensorLog(sensorLog.SensorID == "S2", "Temperature");
Not run here. sensorLog is a 6-by-2 timetable with the variables SensorID (categorical) and Temperature. s1 and s2 are one-variable timetables with the rows of one sensor each. A file with a timestamp column that MATLAB does not recognise as a date needs setvaropts(opts,"Time",InputFormat=...) first (see Dates and Times).
Numeric row times (R2026b)
Since R2026b a timetable can have numeric row times (double or single), which label rows with unit-agnostic quantities such as distance, depth or a day number rather than a clock time. The heatflow plate offers a natural example: temperatures along a line of sensors, labelled by distance from the edge.
With numeric row times the subscript TT(3,:) still means the third row. To select by row-time value, wrap the values in labels, which was introduced in R2026b for this purpose.
Distance = [0.0; 0.1; 0.2; 0.3]; % metres from the left edge
Temperature = [21.5; 22.0; 22.6; 23.1];
profile = timetable(Temperature, RowTimes=Distance);
byRow = profile(3, :); % the third row, at distance 0.2
byLabel = profile(labels(0.3), :); % the row whose row time is 0.3
Not run here. byRow is the row with the row time 0.2 and byLabel the row at 0.3. timerange, withtol and retime accept numeric values for such a timetable, and lag accepts a labels object for the shift. The numeric row times must all be double or all single, and timerange bounds must be numeric of the same class. Releases before R2026b reject numeric row times; keep the distance in a table variable (a plain table) for older code.
Source: MATLAB documentation: labels
Selecting rows by time
A timetable is indexed like a table with position, logical masks and variable names. Because rows have times, three subscript objects select by time.
| Subscript | Selects |
|---|---|
|
Rows whose time is in the half-open interval from |
|
Rows whose time matches one of |
|
Rows whose numeric row time equals one of |
Datetime scalars can also index rows directly: TT(datetime(2026,1,15,10,2,0),:) selects the row at exactly that time.
firstTwo = S1(timerange(datetime(2026,1,15,10,0,0), datetime(2026,1,15,10,2,0)), :); % 10:00 and 10:01
whole = S1(timerange("2026-01-15", "days"), :); % the whole day
near = sensorLog(withtol(datetime(2026,1,15,10,1,0), seconds(5)), :); % rows within 5 s of 10:01:00
Not run here. firstTwo has two rows because the end time is excluded.
Source: MATLAB documentation: timerange
retime: resample and aggregate
TT2 = retime(TT1, newTimes, method) is the central function: it returns a timetable with new row times and new data. Its forms are:
TT2 = retime(TT1,newTimeStep,method)
TT2 = retime(TT1,"regular",method,TimeStep=dt)
TT2 = retime(TT1,"regular",method,SampleRate=Fs)
TT2 = retime(TT1,newTimes,method)
and the same without method (the default). The inputs are:
-
newTimeStep, a name from the listyearly,quarterly,monthly,weekly,daily,hourly,minutelyorsecondly;dt, aduration,calendarDurationor numeric scalar of any size;Fs, a sample rate in Hz; ornewTimes, a sorted, uniquedatetime,durationor numeric vector, which can be irregular. -
method, which is a character vector, a string scalar or a function handle.
| Method family | Methods and behavior |
|---|---|
Fill |
|
Nearest neighbour |
|
Interpolation |
|
Aggregation |
|
|
The default when no method is given: fill with missing values, or the per-variable methods given by the |
As the documentation puts it, the first row time of TT2 is on the time step before the earliest row time of TT1, and the row times of TT2 cover the range of TT1 but may not include any of its actual row times.
Per-variable methods are set with TT.Properties.VariableContinuity = ["continuous" "step" "event" ...] (one entry per variable; unset is the default). A continuous variable (a temperature) is interpolated, a step variable (a mode setting) holds its previous value, and an event variable (a count of events) is filled with missing values. The default method then uses these. Retiming with an explicit method overrides them.
The sensor log resampled to one-minute means
% Not run here: one-minute means for sensor S1 of the log read above
oneMinute = retime(s1, "minutely", "mean");
% Interpolate to a regular 15 second grid instead
fine = retime(s1, "regular", "linear", TimeStep=seconds(15));
% Aggregate without skipping the gaps: a function handle sees NaN
strict = retime(s1, "minutely", @mean);
Not run here. With the six-row sample above, s1 has readings at 10:00:00, 10:01:00 and 10:02:00 for sensor S1 (the S2 rows were removed by the mask), so oneMinute has one row per minute bin with the mean of the readings in the bin. If a bin held the NaN gap, mean would skip it and the bin would hold the mean of the other readings; the function-handle form strict returns NaN for such a bin. fine has rows every 15 seconds, filled by linear interpolation between the neighbouring readings. Treat NaN gaps before interpolating (see Missing Data).
Source: MATLAB documentation: retime
retime also resolves duplicate or irregular times: retiming a timetable that has repeated row times to a regular step aggregates the duplicates, and retime(TT,"regular","firstvalue",TimeStep=...) keeps one value per step.
synchronize: combine timetables on a common time vector
TT = synchronize(TT1,TT2) combines the variables of several timetables in one, on the union of their row times. It is like a horizontal concatenation that allows different row times, and it inserts missing values where a timetable has no data. Variables with the same name in the inputs are renamed. More control:
TT = synchronize(TT1,TT2,newTimeBasis,method)
TT = synchronize(TT1,TT2,newTimeStep,method)
TT = synchronize(TT1,TT2,"regular",method,TimeStep=dt)
TT = synchronize(TT1,TT2,newTimes,method)
TT = synchronize(TT1,...,TTN,___)
-
newTimeBasisis one ofunion(default),intersection,commonrange,firstorlast: how the output row times are built from the input row times.firstandlasttake the row times of the first or the last input timetable. -
The other arguments and the methods are the ones of
retime. Ifmethodis omitted,VariableContinuityor missing-value fill applies.
% Not run here: put the two sensors side by side on a common one-minute grid
both = synchronize(s1, s2, "minutely", "mean");
Not run here. both has one row per minute and two temperature variables; because both inputs have a variable called Temperature, MATLAB renames them (commonly by adding a suffix), so rename the variables first with renamevars when you need predictable names.
lag and other time-based operations
-
lag(TT)shifts the data forward in time by one row (a lag) and puts a missing value in the first row;lag(TT,n)shifts bynrows (negativenshifts backward: a lead);lag(TT,dt)shifts by a time interval that is a multiple of the time step, and may be alabelsobject for numeric row times. The row times of the timetable are unchanged, and it must be regular. -
sortrows(TT)sorts by row times.unique(TT.Time)finds repeated times.isregular(TT)andTT.Properties.TimeSteptest and describe regularity. Row times need not be sorted or unique when the timetable is created, but many functions require it. -
diff(TT.Time)returns the time differences as adurationvector;seconds(...),minutes(...)andhours(...)convert (see Dates and Times). -
eventtableandeventfilter(since R2023a) attach tables of events to a timetable and select rows around the events.
prev = lag(oneMinute); % previous minute's mean in each row
delta = oneMinute.Temperature - prev.Temperature; % change from the previous minute
Not run here. The first row of delta is NaN, because lag fills the first row with a missing value.
Source: MATLAB documentation: lag
Calculations and plots
Since R2023a, mathematical operations such as +, .* and mean can be applied directly to a timetable when all variables support the operation (see Tables); since R2026b, *, / and \ accept a scalar operand. Grouped calculations by calendar unit use groupsummary with a time bin, as in groupsummary(TT,"Time","hour","mean"); like the named retime aggregations, the named groupsummary methods omit NaN values. Plotting functions accept a timetable followed by variable names; with no x variable, they plot against the row times, as in plot(S1,"Temperature"), and stackedplot(both) draws one axis per variable on a shared time axis.
Common errors and pitfalls
The exact message and identifier for these cases vary by release and were not run here; the causes are documented behavior.
-
Row times of the wrong type in a subscript.
timerange,withtolandlabelsmust match the row-time type: adatetimerange ondurationrow times, or numeric bounds ondatetimerow times, is an error. -
Numeric subscripts are positions, not times. On a timetable with numeric row times,
TT(3,:)is the third row. Uselabelsfor the value. -
timerangeexcludes the end. The interval is half-open: to include the last row use theclosedinterval type or a later end time. -
Unsorted or duplicate row times. Interpolating methods need sorted, unique row times; aggregation methods need sorted
newTimes. Sort withsortrows(TT)and aggregate duplicates first withretimeorgroupsummary. -
retimewithNaNdata. Named aggregations skip missing values, so ameanover a bin of allNaNgivesNaNand acountof 0. Interpolation does not repair a gap; usefillmissingorrmmissingfirst. -
First row time of
retime. With a named time step the first output time depends on the step and the earliest input time (the documentation says it is on the time step before the earliest row time), which can surprise when only a few rows exist. GivenewTimesto control it. -
lagof an irregular timetable.lagrequires regular row times; retime to a regular grid first. -
Time zones and daylight-saving.
datetimerow times with a time zone are compared in absolute time. Make all timetables you combine use the same time zone or none (see Dates and Times). -
Row-time variable name. The dimension is
Timeby default, even if the input wast. Rename withTT.Properties.DimensionNames{1} = "Timestamp"orDimensionNames=at creation.
Where older books differ
-
Books from before R2016b describe time series with the
timeseriesobject (in base MATLAB) anddatenumcolumns in matrices or tables, anddatestr/datenumfor formatting. Thedatetimetype and thetimetablethat uses it (R2016b) replace them.timeseries2timetableandtable2timetableconvert old data. -
retime,synchronizeand thetimerangeandwithtolsubscripts arrived withtimetableand are newer than most books.lagandisregularextensions, events (R2023a), and numeric row times withlabels(R2026b) are newer still. -
Old code writes name-value pairs as
'TimeStep',dt; current code can useTimeStep=dt(R2021a, per theretimedocumentation). Both still work.