Esc
Start typing to search...

Table Module

Cross-tabulation and summary tables from DataFrames.

Inspired by Stata's table command, with idiomatic Keel syntax (pipes, data-last, builder pattern).

Quick forms

import Table
import DataFrame

let df = DataFrame.readCsv "data.csv"

-- One-way frequency table
df |> Table.freq "sex"

-- Two-way cross-tabulation
df |> Table.cross "sex" "highbp"

Builder pattern

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.cols ["highbp"]
    |> Table.count
    |> Table.meanOf "age"
    |> Table.show

Nesting vs adjacency

  • Multiple vars in one call = nested hierarchy: Table.rows ["sex", "race"]
  • Multiple calls = adjacent sections: Table.cols ["sex"] |> Table.cols ["race"]

Statistics

FunctionDescription
countFrequency count (default if none specified)
percentPercentage of total
meanOf vMean of variable
sdOf vStandard deviation
medianOf vMedian
minOf v / maxOf vMin / Max
sumOf vSum

Layout

Tables separate data from layout. Use Table.relayout to rearrange dimensions without recomputing statistics. Use Table.toDataFrame to convert to a flat DataFrame for further analysis.

Functions

Table.cols

[String] -> TableSpec -> TableSpec

Add column dimension variables.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", bp = "high" }, { sex = "F", bp = "low" }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.cols ["bp"]
    |> Table.show
Try it

Notes: Multiple calls create adjacent column groups. Multiple vars in one call create nested hierarchy.

See also: Table.rows, Table.create

Table.count

TableSpec -> TableSpec

Add frequency count statistic.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M" }, { sex = "M" }, { sex = "F" }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.count
    |> Table.show
Try it

Notes: If no stat functions are called before Table.show, count is the default.

See also: Table.percent, Table.meanOf

Table.create

DataFrame -> TableSpec

Initialize a table specification builder from a DataFrame.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "F", age = 25 }]

df
    |> Table.create
Try it

Notes: Use Table.rows, Table.cols, and stat functions to configure the table, then Table.show to materialize it.

See also: Table.rows, Table.cols, Table.show

Table.cross

a -> b -> DataFrame -> Table

Create a two-way cross-tabulation. Accepts String or [String] for each dimension.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", bp = "high" }, { sex = "F", bp = "low" }, { sex = "M", bp = "low" }]

df
    |> Table.cross "sex" "bp"
Try it

Notes: Shortcut for Table.create |> Table.rows rowVars |> Table.cols colVars |> Table.count |> Table.show.

See also: Table.freq, Table.create

Table.facetBy

String -> TableSpec -> TableSpec

Split into separate sub-tables for each level of the given variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", race = "W", age = 30 }, { sex = "F", race = "B", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.facetBy "race"
    |> Table.show
Try it

See also: Table.rows, Table.cols

Table.freq

a -> DataFrame -> Table

Create a one-way frequency table. Accepts a String or [String].

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M" }, { sex = "M" }, { sex = "F" }]

df
    |> Table.freq "sex"
Try it

Notes: Shortcut for Table.create |> Table.rows vars |> Table.count |> Table.show.

See also: Table.cross, Table.create

Table.maxOf

String -> TableSpec -> TableSpec

Add maximum of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.maxOf "age"
    |> Table.show
Try it

See also: Table.minOf

Table.meanOf

String -> TableSpec -> TableSpec

Add mean of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.meanOf "age"
    |> Table.show
Try it

See also: Table.sdOf, Table.medianOf

Table.medianOf

String -> TableSpec -> TableSpec

Add median of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.medianOf "age"
    |> Table.show
Try it

See also: Table.meanOf, Table.minOf, Table.maxOf

Table.minOf

String -> TableSpec -> TableSpec

Add minimum of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.minOf "age"
    |> Table.show
Try it

See also: Table.maxOf

Table.noTotals

TableSpec -> TableSpec

Suppress row and column totals.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M" }, { sex = "M" }, { sex = "F" }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.noTotals
    |> Table.show
Try it

Table.percent

TableSpec -> TableSpec

Add percentage of total statistic.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M" }, { sex = "M" }, { sex = "F" }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.percent
    |> Table.show
Try it

See also: Table.count

Table.relayout

[String] -> [String] -> Table -> Table

Re-layout an existing Table with new row and column dimensions.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", bp = "high" }, { sex = "F", bp = "low" }, { sex = "M", bp = "low" }]

let t =
    df |> Table.cross "sex" "bp"

t
    |> Table.relayout ["bp"] ["sex"]
Try it

Notes: First argument is new row variables, second is new column variables. No recomputation of statistics.

See also: Table.show

Table.rows

[String] -> TableSpec -> TableSpec

Add row dimension variables.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.show
Try it

Notes: Multiple calls create adjacent row sections. Multiple vars in one call create nested hierarchy.

See also: Table.cols, Table.create

Table.sdOf

String -> TableSpec -> TableSpec

Add standard deviation of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.sdOf "age"
    |> Table.show
Try it

See also: Table.meanOf

Table.show

TableSpec -> Table

Materialize the table specification into a displayable Table.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.count
    |> Table.show
Try it

Notes: Computes all statistics and creates the table with the current layout. Use Table.relayout to rearrange after.

See also: Table.relayout, Table.toDataFrame

Table.sumOf

String -> TableSpec -> TableSpec

Add sum of a variable.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.sumOf "age"
    |> Table.show
Try it

See also: Table.count, Table.meanOf

Table.toDataFrame

Table -> DataFrame

Convert a Table to a flat DataFrame.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M" }, { sex = "F" }, { sex = "M" }]

let t =
    df |> Table.freq "sex"

t
    |> Table.toDataFrame
Try it

Notes: Returns the raw aggregated data as a DataFrame for further manipulation.

See also: Table.show

Table.withPValue

TableSpec -> TableSpec

Add p-value column with auto-selected test.

Example:
import Table
import DataFrame

let df =
    DataFrame.fromRecords [{ sex = "M", age = 30 }, { sex = "M", age = 40 }, { sex = "F", age = 25 }]

df
    |> Table.create
    |> Table.rows ["sex"]
    |> Table.count
    |> Table.withPValue
    |> Table.show
Try it

Notes: Selects t-test (Welch's) for continuous variables, chi-squared for categorical. ANOVA for >2 groups.