Using Data Tables¶
A new in-memory Table
is created by creating one or more Column
objects, organize them in a List
and then calling the constructor of ListTable
(which is - at this time - the only implementation of a DataTable
):
Column<Integer> timeStamp = new Column<>("timeStamp", "time rounded to nearest second", int.class, "");
Column<Double> temperature = new Column<>("temperature", "engine temperature in Celcius", double.class, "");
Column<String> remark = new Column<>("remark", "remark", String.class, "");
List<Column<?>> columns = List.of(timeStamp, temperature, remark);
ListTable table = new ListTable("engineTemperatureData", "engine temperature samples", columns);
One way to add a record is to provide an array with the values in the same order as used when constructing the table:
Object[] rowData = new Object[] { 600, 18.0, "starting engine" };
table.addRow(rowData);
Another way uses a Map that maps the column names to values of the appropriate types:
Map<String, Object> map = new HashMap<>();
map.put("remark", "leaving parking lot");
map.put("temperature", 28.5);
map.put("timeStamp", 660);
table.addRowByColumnIds(map);
The contents in the Table
can only be accessed sequentially:
for (Row row : table)
for (int column = 0; column < table.getNumberOfColumns(); column++)
System.out.println("column " + column + ": " + row.getValues()[column]);
This outputs:
column 0: 600 column 1: 18.0 column 2: starting engine column 0: 660 column 1: 28.5 column 2: leaving parking lot
The values within a Row
can also be accessed by id
:
for (Row row : table)
System.out.println("timeStamp=" + row.getValue("timeStamp") + ", temperature="
+ row.getValue("temperature") + ", " + row.getValue("remark"));
This outputs:
timeStamp=600, temperature=18.0, starting engine timeStamp=660, temperature=28.5, leaving parking lot
The in-memory table can be written to disk with code like:
JsonData.writeData("C:/Temp/example.json", table);
This directory (C:/Temp) should exist and be writable for this to succeed (if not, an IOException will be thrown). When successful, a file is written that contains the following text:
{
"table": {
"id": "engineTemperatureData",
"description": "engine temperature samples",
"class": "org.djutils.data.ListTable",
"columns": [
{
"nr": 0,
"id": "timeStamp",
"description": "time rounded to nearest second",
"type": "java.lang.Integer",
"unit": ""
},
{
"nr": 1,
"id": "temperature",
"description": "engine temperature in Celcius",
"type": "java.lang.Double",
"unit": ""
},
{
"nr": 2,
"id": "remark",
"description": "remark",
"type": "java.lang.String",
"unit": ""
}
]
},
"data": [
[{"0":"600"},{"1":"18.0"},{"2":"starting engine"}],
[{"0":"660"},{"1":"28.5"},{"2":"leaving parking lot"}]
]
}
If you know a little bit about JSON format, you will recognize that this file describes the data format, followed by two records with the data values. Floating point values are stored as strings. This is done to ensure that even NaN
(Not a Number), Infinity
and -Infinity
(negative infinity) can be stored and retrieved.
This data can be read back with code like:
Table readBack = JsonData.readData("C:/Temp/example.json");
Storing into and reading back from an XML file is very similar:
XmlData.writeData("C:/Temp/example.xml", table);
Table readBack = XmlData.readData("C:/Temp/example.xml");
To store in CSV or TSV format, two file names must be provided because the meta-data can not be stored in the same file as the contents:
CsvData.writeData("C:/Temp/example.csv", "C:/Temp/example.csvm", table);
Table readBack = CsvData.readData("C:/Temp/example.csv", "C:/Temp/example.csvm");
TsvData.writeData("C:/Temp/example.tsv", "C:/Temp/example.tsvm", table);
Table readBack = TsvData.readData("C:/Temp/example.tsv", "C:/Temp/example.tsvm");
Many programs, including Microsoft Excel can open and read these CSV and TSV files, although many (including Excel) will not correctly parse NaN
, Infinity
and -Infinity
values.
Strongly typed quantities¶
The DJUNITS project implements strongly typed quantities that protect the programmer from mixing up times with speeds, etc. This project is fully compatible with strongly typed quantities. The only disadvantage is that the stored data files may not be so easily imported by other software. To create a table with strongly typed quantities, use code like:
Column<Time> timeStamp = new Column<>("timeStamp",
"time rounded to nearest second", Time.class, "s");
Column<AbsoluteTemperature> temperature =
new Column<>("temperature", "engine temperature in Celcius",
AbsoluteTemperature.class, "K");
Column<String> remark = new Column<>("remark", "remark", String.class, "");
List<Column<?>> columns = new ArrayList<>();
columns.add(timeStamp);
columns.add(temperature);
columns.add(remark);
ListTable table = new ListTable("engineTemperatureData",
"engine temperature samples", columns);
Beware that the Time
type in this code is org.djunits.value.vdouble.scalar.Time
. To put in some data use code like:
Object[] record = new Object[] {
new Time(600, TimeUnit.BASE_SECOND),
new AbsoluteTemperature(18.0, AbsoluteTemperatureUnit.DEGREE_CELSIUS),
"starting engine" };
table.addRow(record);
or
Map<String, Object> map = new HashMap<>();
map.put("remark", "leaving parking lot");
map.put("temperature", new AbsoluteTemperature(28.5, AbsoluteTemperatureUnit.DEGREE_CELSIUS));
map.put("timeStamp", new Time(660, TimeUnit.BASE_SECOND));
table.addRowByColumnIds(map);
The code that prints the contents of the in-memory table is exactly the same. The output differs slightly:
column 0: 600.000000 s column 1: 18.0000000 °C column 2: starting engine column 0: 660.000000 s column 1: 28.5000000 °C column 2: leaving parking lot
Please notice that the printed values are now printed with their units.
When stored in a JSON file, there are corresponding differences in the column definitions and the data values:
{
"table": {
"id": "engineTemperatureData",
"description": "engine temperature samples",
"class": "org.djutils.data.ListTable",
"columns": [
{
"nr": 0,
"id": "timeStamp",
"description": "time rounded to nearest second",
"type": "org.djunits.value.vdouble.scalar.Time",
"unit": "s"
},
{
"nr": 1,
"id": "temperature",
"description": "engine temperature in Celcius",
"type": "org.djunits.value.vdouble.scalar.AbsoluteTemperature",
"unit": "K"
},
{
"nr": 2,
"id": "remark",
"description": "remark",
"type": "java.lang.String",
"unit": ""
}
]
},
"data": [
[{"0":"600.0"},{"1":"291.15"},{"2":"starting engine"}],
[{"0":"660.0"},{"1":"301.65"},{"2":"leaving parking lot"}]
]
}
Similar differences occur when storing in XML, CSV, or TSV files. Of course, on read back, the reconstructed Table
is exactly the same, regardless of the storage format used.