table

package
v0.0.0-...-abd1f79 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2017 License: BSD-3-Clause Imports: 9 Imported by: 10

Documentation

Overview

Package table implements ordered, grouped two dimensional relations.

There are two related abstractions: Table and Grouping.

A Table is an ordered relation of rows and columns. Each column is a Go slice and hence must be homogeneously typed, but different columns may have different types. All columns in a Table have the same number of rows.

A Grouping generalizes a Table by grouping the Table's rows into zero or more groups. A Table is itself a Grouping with zero or one groups. Most operations take a Grouping and operate on each group independently, though some operations sub-divide or combine groups.

The structures of both Tables and Groupings are immutable. They are constructed using a Builder or a GroupingBuilder, respectively, and then "frozen" into their respective immutable data structures.

Index

Examples

Constants

This section is empty.

Variables

View Source
var RootGroupID = GroupID{}

RootGroupID is the root of the GroupID tree.

Functions

func ColType

func ColType(g Grouping, col string) reflect.Type

ColType returns the type of column col in g. This will always be a slice type, even if col is a constant column. ColType panics if col is unknown.

TODO: If I introduce a first-class representation for a grouped column, this should probably be in that.

func Fprint

func Fprint(w io.Writer, g Grouping, formats ...string) error

Fprint prints Grouping g to w. formats[i] specifies a fmt-style format string for column i. If there are more columns than formats, remaining columns are formatted with %v (in particular, formats may be omitted entirely to use %v for all columns). Numeric columns are right aligned; all other column types are left aligned.

Example
tab := new(Builder).
	Add("name", []string{"Washington", "Adams", "Jefferson"}).
	Add("terms", []int{2, 1, 2}).
	Done()
Fprint(os.Stdout, tab)
Output:

name        terms
Washington      2
Adams           1
Jefferson       2

func MapCols

func MapCols(g Grouping, f interface{}, incols ...string) func(outcols ...string) Grouping

MapCols applies f to a set of input columns to construct a set of new output columns.

For each Table in g, MapCols calls f(in[0], in[1], ..., out[0], out[1], ...) where in[i] is column incols[i]. f should process the values in the input column slices and fill output columns slices out[j] accordingly. MapCols returns a new Grouping that adds each outcols[j] bound to out[j].

If all of the input columns are constant for a given table, MapCols will call f with all slices of length 1. The input column slices will contain the constant column values and MapCols will bind each output column value out[i][0] as a constant.

func Print

func Print(g Grouping, formats ...string) error

Print(...) is shorthand for Fprint(os.Stderr, ...).

Types

type Builder

type Builder struct {
	// contains filtered or unexported fields
}

A Builder constructs a Table one column at a time.

The zero value of a Builder represents an empty Table.

func NewBuilder

func NewBuilder(t *Table) *Builder

NewBuilder returns a new Builder. If t is non-nil, it populates the new Builder with the columns from t.

func (*Builder) Add

func (b *Builder) Add(name string, data Slice) *Builder

Add adds a column to b, or removes the named column if data is nil. If b already has a column with the given name, Add replaces it. If data is non-nil, it must have the same length as any existing columns or Add will panic.

func (*Builder) AddConst

func (b *Builder) AddConst(name string, val interface{}) *Builder

AddConst adds a constant column to b whose value is val. If b already has a column with this name, AddConst replaces it.

A constant column has the same value in every row of the Table. It does not itself have an inherent length.

func (*Builder) Done

func (b *Builder) Done() *Table

Done returns the constructed Table and resets b.

func (*Builder) Has

func (b *Builder) Has(name string) bool

Has returns true if b has a column named "name".

type GroupID

type GroupID struct {
	// contains filtered or unexported fields
}

GroupID identifies a group. GroupIDs form a tree, rooted at RootGroupID (which is also the zero GroupID).

func (GroupID) Extend

func (g GroupID) Extend(label interface{}) GroupID

Extend returns a new GroupID that is a child of GroupID g. The returned GroupID will not be equal to any existing GroupID (even if label is not unique among g's children). The label is primarily diagnostic; the table package uses it only when printing tables, but callers may store semantic information in group labels.

func (GroupID) Label

func (g GroupID) Label() interface{}

Label returns the label of g.

func (GroupID) Parent

func (g GroupID) Parent() GroupID

Parent returns the parent of g. The parent of RootGroupID is RootGroupID.

func (GroupID) String

func (g GroupID) String() string

String returns the path to GroupID g in the form "/l1/l2/l3". If g is RootGroupID, it returns "/". Each level in the group is formed by formatting the label using fmt's "%v" verb. Note that this is purely diagnostic; this string may not uniquely identify g.

type Grouping

type Grouping interface {
	// Columns returns the names of the columns in this Grouping,
	// or nil if there are no Tables or the group consists solely
	// of empty Tables. All Tables in this Grouping have the same
	// set of columns.
	Columns() []string

	// Tables returns the group IDs of the tables in this
	// Grouping.
	Tables() []GroupID

	// Table returns the Table in group gid, or nil if there is no
	// such Table.
	Table(gid GroupID) *Table
}

A Grouping is an immutable set of tables with identical sets of columns, each identified by a distinct GroupID.

Visually, a Grouping can be thought of as follows:

   Col A  Col B  Col C
------ group /a ------
0   5.4    "x"     90
1   -.2    "y"     30
------ group /b ------
0   9.3    "a"     10

Like a Table, a Grouping's structure is immutable. To construct a Grouping, use a GroupingBuilder.

Despite the fact that GroupIDs form a hierarchy, a Grouping ignores this hierarchy and simply operates on a flat map of distinct GroupIDs to Tables.

func Concat

func Concat(gs ...Grouping) Grouping

Concat returns the concatenation of the rows in each matching group across gs. All Groupings in gs must have the same set of columns (though they need not be in the same order; the column order from gs[0] will be used). The GroupIDs in the returned Grouping will be the union of the GroupIDs in gs.

func Filter

func Filter(g Grouping, pred interface{}, cols ...string) Grouping

Filter filters g to only rows where pred returns true. pred must be a function that returns bool and takes len(cols) arguments where the type of col[i] is assignable to argument i.

TODO: Create a faster batch variant where pred takes slices.

func FilterEq

func FilterEq(g Grouping, col string, val interface{}) Grouping

FilterEq filters g to only rows where the value in col equals val.

func GroupBy

func GroupBy(g Grouping, cols ...string) Grouping

GroupBy sub-divides all groups such that all of the rows in each group have equal values for all of the named columns. The relative order of rows with equal values for the named columns is maintained. Grouped-by columns become constant columns within each group.

func Head(g Grouping, n int) Grouping

Head returns the first n rows in each Table of g.

func HeadTables

func HeadTables(g Grouping, n int) Grouping

HeadTables returns the first n tables in g.

func Join

func Join(g1 Grouping, col1 string, g2 Grouping, col2 string) Grouping

Join joins g1 and g2 on tables with identical group IDs where col1 in g1 equals col2 in g2. It maintains the group order of g1, except that groups that aren't in g2 are removed, and maintains the row order of g1, followed by the row order of g2.

TODO: Support join on more than one column.

func MapTables

func MapTables(g Grouping, f func(gid GroupID, table *Table) *Table) Grouping

MapTables applies f to each Table in g and returns a new Grouping with the same group structure as g, but with the Tables returned by f.

func Pivot

func Pivot(g Grouping, label, value string) Grouping

Pivot converts rows of g into columns. label and value must name columns in g, and the label column must have type []string. Pivot returns a Grouping with a new column named after each distinct value in the label column, where the values in that column correspond to the values from the value column. All other columns (besides label and value) are copied to the output. If, for a given column in an output row, no input row has that column in the label column, the output cell will have the zero value for its type.

Example
fmt.Println("Original table")
Print(stateTempByKind)
fmt.Println()
fmt.Println("Pivoted table")
Print(Pivot(stateTempByKind, "kind", "temperature"))
Output:


Original table
state    kind  temperature
Alabama  high          122
Alabama  low           -27
Alaska   high          100
Alaska   low           -80

Pivoted table
state    high  low
Alabama   122  -27
Alaska    100  -80

func Remove

func Remove(g Grouping, col string) Grouping

Remove returns g with column 'col' removed.

func Rename

func Rename(g Grouping, from, to string) Grouping

Rename returns g with column 'from' renamed to 'to'. The column retains its position.

func SortBy

func SortBy(g Grouping, cols ...string) Grouping

SortBy sorts each group of g by the named columns. If a column's type implements sort.Interface, rows will be sorted according to that order. Otherwise, the values in the column must be naturally ordered (their types must be orderable by the Go specification). If neither is true, SortBy panics with a *generic.TypeError. If more than one column is given, SortBy sorts by the tuple of the columns; that is, if two values in the first column are equal, they are sorted by the second column, and so on.

func Tail

func Tail(g Grouping, n int) Grouping

Tail returns the last n rows in each Table of g.

func TailTables

func TailTables(g Grouping, n int) Grouping

TailTables returns the first n tables in g.

func Ungroup

func Ungroup(g Grouping) Grouping

Ungroup concatenates adjacent Tables in g that share a group parent into a Table identified by the parent, undoing the effects of the most recent GroupBy operation.

func Unpivot

func Unpivot(g Grouping, label, value string, cols ...string) Grouping

Unpivot converts columns of g into rows. The returned Grouping consists of the columns of g *not* listed in cols, plus two columns named by the label and value arguments. For each input row in g, the returned Grouping will have len(cols) output rows. The i'th such output row corresponds to column cols[i] in the input row. The label column will contain the name of the unpivoted column, cols[i], and the value column will contain that column's value from the input row. The values of all other columns in the input row will be repeated across the output rows. All columns in cols must have the same type.

Example
fmt.Println("Original table")
Print(stateTemp)
fmt.Println()
fmt.Println("Unpivoted table")
Print(Unpivot(stateTemp, "kind", "temperature", "high", "low"))
Output:


Original table
state    high  low
Alabama   122  -27
Alaska    100  -80

Unpivoted table
state    kind  temperature
Alabama  high          122
Alabama  low           -27
Alaska   high          100
Alaska   low           -80

type GroupingBuilder

type GroupingBuilder struct {
	// contains filtered or unexported fields
}

A GroupingBuilder constructs a Grouping one table a time.

The zero value of a GroupingBuilder represents an empty Grouping with no tables and no columns.

func NewGroupingBuilder

func NewGroupingBuilder(g Grouping) *GroupingBuilder

NewGroupingBuilder returns a new GroupingBuilder. If g is non-nil, it populates the new GroupingBuilder with the tables from g.

func (*GroupingBuilder) Add

func (b *GroupingBuilder) Add(gid GroupID, t *Table) *GroupingBuilder

Add adds a Table to b, or removes a table if t is nil. If t is the empty Table, this is a no-op because the empty Table contains no groups. If gid already exists, Add replaces it. Table t must have the same columns as any existing Tables in this Grouping and they must have identical types; otherwise, Add will panic.

TODO This doesn't make it easy to combine two Groupings. It could instead take a Grouping and reparent it.

func (*GroupingBuilder) Done

func (b *GroupingBuilder) Done() Grouping

Done returns the constructed Grouping and resets b.

type Slice

type Slice interface{}

A Slice is a Go slice value.

This is primarily for documentation. There is no way to statically enforce this in Go; however, functions that expect a Slice will panic with a *generic.TypeError if passed a non-slice value.

type Table

type Table struct {
	// contains filtered or unexported fields
}

A Table is an immutable, ordered two dimensional relation. It consists of a set of named columns. Each column is a sequence of values of a consistent type or a constant value. All (non-constant) columns have the same length.

The zero value of Table is the "empty table": it has no rows and no columns. Note that a Table may have one or more columns, but no rows; such a Table is *not* considered empty.

A Table is also a trivial Grouping. If a Table is empty, it has no groups and hence the zero value of Table is also the "empty group". Otherwise, it consists only of the root group, RootGroupID.

func Flatten

func Flatten(g Grouping) *Table

Flatten concatenates all of the groups in g into a single Table. This is equivalent to repeatedly Ungrouping g.

func TableFromStrings

func TableFromStrings(cols []string, rows [][]string, coerce bool) *Table

TableFromStrings converts a [][]string to a Table. This is intended for processing external data, such as from CSV files. If coerce is true, TableFromStrings will convert columns to []int or []float when every string in that column is accepted by strconv.ParseInt or strconv.ParseFloat, respectively.

Example
const csvData = `name,terms
Washington,2
Adams,1
Jefferson,2`
rows, _ := csv.NewReader(bytes.NewBufferString(csvData)).ReadAll()
Print(TableFromStrings(rows[0], rows[1:], true))
Output:

name        terms
Washington      2
Adams           1
Jefferson       2

func TableFromStructs

func TableFromStructs(structs Slice) *Table

TableFromStructs converts a []T where T is a struct to a Table where the columns of the table correspond to T's exported fields.

Example
type prez struct {
	Name  string
	Terms int
}
data := []prez{{"Washington", 2}, {"Adams", 1}, {"Jefferson", 2}}
Print(TableFromStructs(data))
Output:

Name        Terms
Washington      2
Adams           1
Jefferson       2

func (*Table) Column

func (t *Table) Column(name string) Slice

Column returns the slice of data in column name of Table t, or nil if there is no such column. If name is a constant column, this returns a slice with the constant value repeated to the length of the Table.

func (*Table) Columns

func (t *Table) Columns() []string

Columns returns the names of the columns in Table t, or nil if this Table is empty.

func (*Table) Const

func (t *Table) Const(name string) (val interface{}, ok bool)

Const returns the value of constant column name. If this column does not exist or is not a constant column, Const returns nil, false.

func (*Table) Len

func (t *Table) Len() int

Len returns the number of rows in Table t.

func (*Table) MustColumn

func (t *Table) MustColumn(name string) Slice

MustColumn is like Column, but panics if there is no such column.

func (*Table) Table

func (t *Table) Table(gid GroupID) *Table

Table returns t if gid is RootGroupID and t is not empty; otherwise it returns nil.

func (*Table) Tables

func (t *Table) Tables() []GroupID

Tables returns the groups IDs in this Table. If t is empty, there are no group IDs. Otherwise, there is only RootGroupID.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL