I am trying to synchronize two tables, how do I do this to keep the date and time format?
4 views (last 30 days)
Show older comments
app.bow_time_axis = datetime(app.bow{:,1:2},'InputFormat',"dd/MM/uuuu HH:mm:ss");
app.bow_timetable = timetable(app.bow_time_axis,app.bow{:,3:4});
app.stern_time_axis = datetime(app.bow{:,1:2},'InputFormat',"dd/MM/uuuu HH:mm:ss");
app.stern_timetable = timetable(app.stern_time_axis,app.bow{:,3:4});
app.comb = synchronize(app.bow_timetable, app.stern_timetable, 'first', 'pchip');
This the error message due to the datetime difficulty:
Unable to concatenate the specified table variables.
Caused by:
Error using datetime/horzcat (line 1341)
All inputs must be datetimes or date/time character vectors or date/time strings.
This is an example of the table format being used (note it is dd/mm/yyyy):
10/10/2020,20:37:00.00,426988.025,5830157.551
2 Comments
Seth Furman
on 14 Feb 2022
Edited: Seth Furman
on 14 Feb 2022
Please include a code example with data so that we can reproduce the error.
Answers (2)
Seth Furman
on 14 Feb 2022
Create example data
bowData = [
"10/10/2020,20:37:00.00,426988.025,5830157.551"
"10/10/2020,20:37:01.00,426988.027,5830157.549"
"10/10/2020,20:37:02.00,426988.029,5830157.552"
"10/10/2020,20:37:03.00,426988.036,5830157.555"
"10/10/2020,20:37:04.00,426988.042,5830157.553"
"10/10/2020,20:37:05.00,426988.042,5830157.553"
"10/10/2020,20:37:06.00,426988.041,5830157.551"
"10/10/2020,20:37:07.00,426988.031,5830157.546"
];
writematrix(bowData, "BOW.txt", "QuoteStrings", false);
sternData = [
"10/10/2020,20:39:59.00,426991.426,5830128.000"
"10/10/2020,20:40:00.00,426991.430,5830127.999"
"10/10/2020,20:40:01.00,426991.431,5830128.005"
"10/10/2020,20:40:02.00,426991.436,5830128.006"
"10/10/2020,20:40:03.00,426991.430,5830128.006"
"10/10/2020,20:40:04.00,426991.425,5830128.007"
"10/10/2020,20:40:05.00,426991.419,5830128.009"
"10/10/2020,20:40:06.00,426991.420,5830128.007"
];
writematrix(sternData, "STERN.txt", "QuoteStrings", false);
Read data
opts = detectImportOptions("BOW.txt");
opts = setvaropts(opts,1, "InputFormat", "MM/dd/uuuu");
ttBow = readtimetable("BOW.txt",opts)
ttBow.Var1 = ttBow.Var1 + ttBow.Var2;
ttBow.Var1.Format = "MM/dd/uuuu HH:mm:ss.SS";
ttBow = removevars(ttBow, "Var2")
ttStern = readtimetable("STERN.txt",opts)
ttStern.Var1 = ttStern.Var1 + ttStern.Var2;
ttStern.Var1.Format = "MM/dd/uuuu HH:mm:ss.SS";
ttStern = removevars(ttStern, "Var2")
Synchronize
synchronize(ttBow, ttStern, "first", "pchip")
0 Comments
Cris LaPierre
on 14 Feb 2022
Edited: Cris LaPierre
on 14 Feb 2022
I think what may be of most help is this page on accessing data in tables. In the end, that is the biggest changes I made. Here are some suggestions:
- You can set the variable names in a single line of code using a cell array
- You can access data in a table using tableNm.varNm
- There is ambiguity in your date format. Specify this using detetectImportOptions and setvaropts.
- You can just add a datetime and a duration to combine date and time.
- Use table2timetable to create your timetable. Use the 'RowTimes' name-value pair to specify the time data. This way, you columns remain separate variables.
- UITable data cannot be a timetable. Convert back to a table using timetable2table.
I believe your error came from using the curly brace syntax to extract array data from your table: app.bow{:,1:2}. Here, column 1 is a datetime, but column 2 is a duration. These are different datatypes, so they cannot be placed into the same array, hence the error.
There may be some other small changes, so I'll share the updated functions below.
% Button pushed function: LoadBowFileButton
function LoadBowFileButtonPushed(app, event)
[app.file,app.path] = uigetfile('*.txt', 'Select file');
opts = detectImportOptions(fullfile(app.path, app.file));
opts = setvaropts(opts,1,"InputFormat","MM/dd/yyyy");
app.bow = readtable(fullfile(app.path, app.file),opts);
app.bow.Properties.VariableNames = {'Date','Time','Easting','Northing'};
app.UITable.ColumnName = app.bow.Properties.VariableNames;
app.UITable.Data = app.bow;
app.x = app.UITable.Data.Easting;
app.y = app.UITable.Data.Northing;
plot(app.UIAxes, app.x, app.y);
title(app.UIAxes,'Bow GNSS');
ylabel(app.UIAxes,'Northing');
xlabel(app.UIAxes,'Easting');
app.bow_time_axis = app.bow.Date + app.bow.Time;
app.bow_time_axis.Format = "MM/dd/yyyy HH:mm:ss";
app.bow_timetable = table2timetable(app.bow(:,3:4),"RowTimes",app.bow_time_axis);
end
% Button pushed function: LoadSternFileButton
function LoadSternFileButtonPushed(app, event)
[app.file,app.path] = uigetfile('*.txt', 'Select file');
app.stern = readtable(fullfile(app.path, app.file));
app.stern.Properties.VariableNames = {'Stern Date','Stern Time','Stern Easting','Stern Northing'};
app.stern_time_axis = app.stern.('Stern Date') + app.stern.('Stern Time');
app.stern_time_axis.Format = "MM/dd/yyyy HH:mm:ss";
app.stern_timetable = table2timetable(app.stern(:,3:4),"RowTimes",app.stern_time_axis);
app.comb = synchronize(app.bow_timetable, app.stern_timetable, 'first', 'pchip');
app.headingtable = table('Size',[height(app.comb) 1],'VariableTypes',{'double'});
for i = 1:1:height(app.comb)
app.bow_easting = app.comb.Easting(i);
app.stern_easting = app.comb.('Stern Easting')(i);
app.bow_northing = app.comb.Northing(i);
app.stern_northing = app.comb.('Stern Northing')(i);
app.heading = atan2d(((app.bow_northing)-(app.stern_northing)),((app.bow_easting)-(app.stern_easting)));
if app.heading > 0
app.headingtable{i,1} = 360 - (app.heading - 90);
elseif app.heading < 0
app.headingtable{i,1} = 90 - app.heading;
elseif app.heading == 0
app.headingtable{i,1} = 90;
end
end
app.final = timetable2table(horzcat(app.comb, app.headingtable));
app.final.Properties.VariableNames = {'Time','BowEasting','BowNorthing','SternEasting','SternNorthing','Heading'};
app.UITable.Data = app.final;
app.UITable.ColumnName = app.final.Properties.VariableNames;
app.x = app.UITable.Data.Time;
app.y = app.UITable.Data.Heading;
plot(app.UIAxes, app.x, app.y);
title(app.UIAxes,'Calculated Heading over Time');
ylabel(app.UIAxes,'Calculated Heading');
xlabel(app.UIAxes,'Time');
end
2 Comments
Cris LaPierre
on 14 Feb 2022
Edited: Cris LaPierre
on 14 Feb 2022
That is not what synchronize does. Instead, it uses the method you specify to fill in the missing data: "Synchronize timetables to common time vector, and resample or aggregate data from input timetables"
You probably want to look into joining tables if you only want to keep that data that corresponds to timestamps present in both tables. I think innerjoin accomplishes what you want.
% Load BOW data
opts = detectImportOptions('BOW.txt');
opts.VariableNames = {'Date','Time','Easting','Northing'};
opts = setvaropts(opts,'Date',"InputFormat","MM/dd/yyyy");
bow = readtable('BOW.txt',opts);
bow.Timestamp = bow.Date + bow.Time;
bow.Timestamp.Format = "MM/dd/uuuu HH:mm:ss"
% Load STERN data
opts = detectImportOptions('STERN.txt');
opts.VariableNames = {'Date','Time','Easting','Northing'};
opts = setvaropts(opts,'Date',"InputFormat","MM/dd/yyyy");
stern = readtable('STERN.txt',opts);
stern.Timestamp = stern.Date + stern.Time;
stern.Timestamp.Format = "MM/dd/uuuu HH:mm:ss"
% Join tables only keeping timestamps common to both
joinedData = innerjoin(bow,stern,"Keys","Timestamp","LeftVariables",...
["Timestamp","Easting","Northing"],"RightVariables",["Easting","Northing"])
See Also
Categories
Find more on Timetables in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!