Input and output

Input and output of Table and FlexTable are mostly handled through externally-defined interfaces.

AbstractArray interface

One can convert an AbstractArray of NamedTuples to a Table using a simple constructor.

julia> v = [(name="Alice", age=25), (name="Bob", age=42), (name= "Charlie", age=37)]
3-element Array{NamedTuple{(:name, :age),Tuple{String,Int64}},1}:
 (name = "Alice", age = 25)  
 (name = "Bob", age = 42)    
 (name = "Charlie", age = 37)

julia> t = Table(v)
Table with 2 columns and 3 rows:
     name     age
   ┌─────────────
 1 │ Alice    25
 2 │ Bob      42
 3 │ Charlie  37

In this way, we have converted a row-based storage container to a column-based storage container.

One can convert back to row-based storage by collecting the results in an Array.

julia> collect(t)
3-element Array{NamedTuple{(:name, :age),Tuple{String,Int64}},1}:
 (name = "Alice", age = 25)  
 (name = "Bob", age = 42)    
 (name = "Charlie", age = 37)

Note that collect is the generic construtor for an Array which accepts any kind of iterable - an "iterable" being any type that supports the iterate function.

Tables.jl

NOTE: The information in this section represents the development versions of Tables, CSV and related packages.

The Tables.jl package provides a flexible interface for dealing with tabular data of all forms: from in-memory Tables to CSV files on a disk.

At it's core, it provides a way of:

  • Introspecting data via Tables.istable, Tables.schema, and so-on.
  • Provide a row iterator via rows(data), where each row has fields/cells accessed by getproperty.
  • Provide a collection of columns via columns(data) that can be accessed via getpropery, each of which iterates fields/cells.

It's simple design allows us to treat many forms of tabular data in the same way.

CSV.jl

As an example of good use of the Tables.jl, take the package CSV.jl, which is designed to load and save CSV files.

Let's say we have a CSV file called input.csv, and the following data.

name,age
Alice,25
Bob,42
Charlie,37

We can load this file from disk using the CSV.File constructor.

julia> using TypedTables, CSV

julia> csvfile = CSV.File("input.csv")
CSV.File("/home/ferris/example.csv", rows=3):
Tables.Schema:
 :name  Union{Missing, String}
 :age   Union{Missing, Int64}

Note that CSV has inferred the column types from the data, but by default allows for missing data. This can be controlled via the allowmissing keyword argument (as either :all, :none or :auto).

julia> CSV.File("input.csv", allowmissing=:none)
CSV.File("/home/ferris/example.csv", rows=3):
Tables.Schema:
 :name  String
 :age   Int64 

Either of these can finally be converted to a Table.

julia> Table(csvfile)
Table with 2 columns and 3 rows:
     name     age
   ┌─────────────
 1 │ Alice    25
 2 │ Bob      42
 3 │ Charlie  37

Similarly, the CSV.jl package supports writing tables with CSV.write function.

julia> CSV.write("output.csv", t)
"output.csv"