POKI_PUT_TOC_HERE

Command overview

Whereas the Unix toolkit is made of the separate executables cat, tail, cut, sort, etc., Miller has subcommands, invoked as follows: POKI_INCLUDE_ESCAPED(subcommand-example.txt)HERE

These falls into categories as follows:
Commands Description
cat, cut, head, sort, tac, tail, top, uniq Analogs of their Unix-toolkit namesakes, discussed below as well as in POKI_PUT_LINK_FOR_PAGE(feature-comparison.html)HERE
filter, put, step awk-like functionality
histogram, stats1, stats2 Statistically oriented
group-by, group-like, having-fields Particularly oriented toward POKI_PUT_LINK_FOR_PAGE(record-heterogeneity.html)HERE, although all Miller commands can handle heterogeneous records
count-distinct, rename These draw from other sources (see also POKI_PUT_LINK_FOR_PAGE(originality.html)HERE): count-distinct is SQL-ish, and rename can be done by sed (which does it faster: see POKI_PUT_LINK_FOR_PAGE(performance.html)HERE).

On-line help

Examples:

POKI_RUN_COMMAND{{mlr --help | fold -s}}HERE POKI_RUN_COMMAND{{mlr sort --help}}HERE

then-chaining

In accord with the Unix philosophy, you can pipe data into or out of Miller. For example: POKI_CARDIFY(mlr cut --complement -f os_version *.dat | mlr sort hostname,uptime)HERE

For better performance (avoiding redundant string-parsing and string-formatting when you pipe Miller commands together) you can, if you like, instead simply chain commands together using the then keyword: POKI_CARDIFY(mlr cut --complement -f os_version then sort hostname,uptime *.dat)HERE

I/O options

Formats

Options:

  --dkvp    --idkvp   --odkvp
  --nidx    --inidx   --onidx
  --csv     --icsv    --ocsv
  --pprint  --ipprint --ppprint --right
  --xtab    --ixtab   --oxtab

These are as discussed in POKI_PUT_LINK_FOR_PAGE(file-formats.html)HERE, with the exception of --right which makes pretty-printed output right-aligned:
POKI_RUN_COMMAND{{mlr --opprint cat data/small}}HERE POKI_RUN_COMMAND{{mlr --opprint --right cat data/small}}HERE

Additional notes:

Record/field/pair separators

Miller has record separators IRS and ORS, field separators IFS and OFS, and pair separators IPS and OPS. For example, in the DKVP line a=1,b=2,c=3, the record separator is newline, field separator is comma, and pair separator is the equals sign. These are the default values.

Options:

  --rs --irs --ors
  --fs --ifs --ofs --repifs
  --ps --ips --ops

Number formatting

Options:
  --ofmt {format string}

This is the global number format for commands which generate numeric output, e.g. stats1, stats2, histogram, and step. Examples: POKI_CARDIFY(--ofmt %.9le --ofmt %.6lf --ofmt %.0lf)HERE

These are just C printf formats applied to double-precision numbers. Please don’t use %s or %d. Additionally, if you use leading with (e.g. %18.12lf) then the output will contain embedded whitespace, which may not be what you want if you pipe the output to something else.

Data transformations

cat

Most useful for format conversions (see POKI_PUT_LINK_FOR_PAGE(file-formats.html)HERE), and concatenating multiple same-schema CSV files to have the same header:
POKI_RUN_COMMAND{{cat a.csv}}HERE POKI_RUN_COMMAND{{cat b.csv}}HERE POKI_RUN_COMMAND{{mlr --csv cat a.csv b.csv}}HERE POKI_RUN_COMMAND{{mlr --icsv --oxtab cat a.csv b.csv}}HERE

count-distinct

POKI_RUN_COMMAND{{mlr count-distinct --help}}HERE

xxx great oppo for sort -nr POKI_RUN_COMMAND{{mlr count-distinct -f a,b then sort count data/medium}}HERE

cut

POKI_RUN_COMMAND{{mlr cut --help}}HERE

Note that cut doesn’t reorder field names — for that, use reorder.
POKI_RUN_COMMAND{{mlr --opprint cat data/small}}HERE POKI_RUN_COMMAND{{mlr --opprint cut -f y,x,i data/small}}HERE

filter

POKI_RUN_COMMAND{{mlr filter --help}}HERE

Field names must be specified using a $ in filter expressions, even though they don’t appear in the data stream. For integer-indexed data, this looks like awk’s $1,$2,$3. POKI_RUN_COMMAND{{ruby -e '10.times{|i|puts "i=#{i}"}' | mlr --opprint put '$j=$i+1;$k=$i+$j'}}HERE

The filter command supports the same built-in variables as for put, all awk-inspired: NF, NR, FNR, FILENUM, and FILENAME. This selects the 2nd record from each matching file: POKI_RUN_COMMAND{{mlr filter 'FNR == 2' data/small*}}HERE

Expressions may be arbitrarily complex: POKI_RUN_COMMAND{{mlr --opprint filter '$a == "pan" || $b == "wye"' data/small}}HERE
POKI_RUN_COMMAND{{mlr --opprint filter '($x > 0.5 && $y > 0.5) || ($x < 0.5 && $y < 0.5)' then stats2 -a corr -f x,y data/medium}}HERE
POKI_RUN_COMMAND{{mlr --opprint filter '($x > 0.5 && $y < 0.5) || ($x < 0.5 && $y > 0.5)' then stats2 -a corr -f x,y data/medium}}HERE

group-by

POKI_RUN_COMMAND{{mlr group-by --help}}HERE

This is similar to sort but with less work. Namely, Miller’s sort has three steps: read through the data and append linked lists of records, one for each unique combination of the key-field values; after all records are read, sort the key-field values; then print each record-list. The group-by operation simply omits the middle sort. An example should make this more clear.
POKI_RUN_COMMAND{{mlr --opprint group-by a data/small}}HERE POKI_RUN_COMMAND{{mlr --opprint sort a data/small}}HERE

In this example, since the sort is on field a, the first step is to group together all records having the same value for field a; the second step is to sort the distinct a-field values pan, eks, and wye into eks, pan, and wye; the third step is to print out the record-list for a=eks, then the record-list for a=pan, then the record-list for a=wye. The group-by operation omits the middle sort and just puts like records together, for those times when a sort isn’t desired. In particular, the ordering of group-by fields for group-by is the order in which they were encountered in the data stream, which in some cases may be more interesting to you.

group-like

POKI_RUN_COMMAND{{mlr group-like --help}}HERE

This groups together records having the same schema (i.e. same ordered list of field names) which is useful for making sense of time-ordered output as described in POKI_PUT_LINK_FOR_PAGE(record-heterogeneity.html)HERE — in particular, in preparation for CSV or pretty-print output.
POKI_RUN_COMMAND{{mlr cat data/het.dkvp}}HERE POKI_RUN_COMMAND{{mlr --opprint group-like data/het.dkvp}}HERE

having-fields

POKI_RUN_COMMAND{{mlr having-fields --help}}HERE

Similar to group-like, this retains records with specified schema.
POKI_RUN_COMMAND{{mlr cat data/het.dkvp}}HERE
POKI_RUN_COMMAND{{mlr having-fields --at-least resource data/het.dkvp}}HERE
POKI_RUN_COMMAND{{mlr having-fields --which-are resource,ok,loadsec data/het.dkvp}}HERE

head

POKI_RUN_COMMAND{{mlr head --help}}HERE Note that head is distinct from tophead shows fields which appear first in the data stream; top shows fields which are numerically largest (or smallest).
POKI_RUN_COMMAND{{mlr --opprint head -n 4 data/medium}}HERE POKI_RUN_COMMAND{{mlr --opprint head -n 1 -g b data/medium}}HERE

histogram

POKI_RUN_COMMAND{{mlr histogram --help}}HERE Just a histogram. POKI_RUN_COMMAND{{mlr --opprint put '$x2=$x**2;$x3=$x2*$x' then histogram -f x,x2,x3 --lo 0 --hi 1 --nbins 10 data/medium}}HERE

put

POKI_RUN_COMMAND{{mlr put --help}}HERE

Field names must be specified using a $ in put expressions, even though they don’t appear in the data stream. For integer-indexed data, this looks like awk’s $1,$2,$3. Multiple expressions may be given, separated by semicolons, and each may refer to the ones before. POKI_RUN_COMMAND{{ruby -e '10.times{|i|puts "i=#{i}"}' | mlr --opprint put '$j=$i+1;$k=$i+$j'}}HERE

Miller supports the following five built-in variables for filter and put, all awk-inspired: NF, NR, FNR, FILENUM, and FILENAME. POKI_RUN_COMMAND{{mlr --opprint put '$nf=NF; $nr=NR; $fnr=FNR; $filenum=FILENUM; $filename=FILENAME' data/small data/small2}}HERE

rename

POKI_RUN_COMMAND{{mlr rename --help}}HERE
POKI_RUN_COMMAND{{mlr --opprint cat data/small}}HERE POKI_RUN_COMMAND{{mlr --opprint rename i,INDEX,b,COLUMN2 data/small}}HERE

As discussed in POKI_PUT_LINK_FOR_PAGE(performance.html)HERE, sed is significantly faster than Miller at doing this. However, Miller is format-aware, so it knows to do renames only within specified field keys and not any others, nor in field values which may happen to contain the same pattern. Example:
POKI_RUN_COMMAND{{sed 's/y/COLUMN5/g' data/small}}HERE
POKI_RUN_COMMAND{{mlr rename y,COLUMN5 data/small}}HERE

reorder

POKI_RUN_COMMAND{{mlr reorder --help}}HERE This pivots specified field names to the start or end of the record — for example when you have highly multi-column data and you want to bring a field or two to the front of line where you can give a quick visual scan.
POKI_RUN_COMMAND{{mlr --opprint cat data/small}}HERE
POKI_RUN_COMMAND{{mlr --opprint reorder -f i,b data/small}}HERE POKI_RUN_COMMAND{{mlr --opprint reorder -e -f i,b data/small}}HERE

sort

POKI_RUN_COMMAND{{mlr sort --help}}HERE

xxx write up after -n/-r.

stats1

POKI_RUN_COMMAND{{mlr stats1 --help}}HERE These are simple univariate statistics on one or more number-valued fields, optionally categorized by one or more fields.
POKI_RUN_COMMAND{{mlr --oxtab stats1 -a count,sum,avg -f x,y data/medium}}HERE
POKI_RUN_COMMAND{{mlr --opprint stats1 -a avg -f x,y -g b then sort b data/medium}}HERE

stats2

POKI_RUN_COMMAND{{mlr stats2 --help}}HERE These are simple bivariate statistics on one or more pairs of number-valued fields, optionally categorized by one or more fields.
POKI_RUN_COMMAND{{mlr --oxtab put '$x2=$x*$x; $xy=$x*$y; $y2=$y**2' then stats2 -a cov,corr -f x,y,y,y,x2,xy,x2,y2 data/medium}}HERE
POKI_RUN_COMMAND{{mlr --opprint put '$x2=$x*$x; $xy=$x*$y; $y2=$y**2' then stats2 -a linreg,r2 -f x,y,y,y,xy,y2 -g a data/medium}}HERE

Here’s an example simple line-fit. The x and y fields of the data/medium dataset are just independent uniformly distributed on the unit interval. Here we remove half the data and fit a line to it. POKI_INCLUDE_ESCAPED(data/linreg-example.txt)HERE

I use pgr for plotting; here’s a screenshot.

step

POKI_RUN_COMMAND{{mlr step --help}}HERE Most Miller commands are record-at-a-time, with the exception of stats1, stats2, and histogram which compute aggregate output. The step command is intermediate: it allows the option of adding fields which are functions of fields from previous records. Rsum is short for running sum.

xxx rename rsum then so it doesn’t need explaining!! :)
POKI_RUN_COMMAND{{mlr --opprint step -a delta,rsum,counter -f x data/medium | head -15}}HERE
POKI_RUN_COMMAND{{mlr --opprint step -a delta,rsum,counter -f x -g a data/medium | head -15}}HERE

tac

POKI_RUN_COMMAND{{mlr tac --help}}HERE

Prints the records in the input stream in reverse order. Note: this requires Miller to retain all input records in memory before any output records are produced.
POKI_RUN_COMMAND{{mlr --icsv --opprint cat a.csv}}HERE POKI_RUN_COMMAND{{mlr --icsv --opprint cat b.csv}}HERE POKI_RUN_COMMAND{{mlr --icsv --opprint tac a.csv b.csv}}HERE
POKI_RUN_COMMAND{{mlr --icsv --opprint put '$filename=FILENAME' then tac a.csv b.csv}}HERE

tail

POKI_RUN_COMMAND{{mlr tail --help}}HERE

Prints the last n records in the input stream, optionally by category.
POKI_RUN_COMMAND{{mlr --opprint tail -n 4 data/colored-shapes.dkvp}}HERE
POKI_RUN_COMMAND{{mlr --opprint tail -n 1 -g shape data/colored-shapes.dkvp}}HERE

top

POKI_RUN_COMMAND{{mlr top --help}}HERE Note that top is distinct from headhead shows fields which appear first in the data stream; top shows fields which are numerically largest (or smallest).
POKI_RUN_COMMAND{{mlr --opprint top -n 4 -f x data/medium}}HERE POKI_RUN_COMMAND{{mlr --opprint top -n 2 -f x -g a then sort a data/medium}}HERE

uniq

POKI_RUN_COMMAND{{mlr uniq --help}}HERE
POKI_RUN_COMMAND{{wc -l data/colored-shapes.dkvp}}HERE
POKI_RUN_COMMAND{{mlr uniq -g color,shape data/colored-shapes.dkvp}}HERE
POKI_RUN_COMMAND{{mlr --opprint uniq -g color,shape -c then sort color,shape data/colored-shapes.dkvp}}HERE

Functions for filter and put

Miller’s filter and put support the following operators and functions:
Operators/functions Description
==, !=, <, <=, >, >=, &&, || Filter-only. Comparisons are string-valued or number-valued depending on absence/presence of double-quotes in the literal value:
mlr filter '$color != "blue" && $value > 4.2'
+, - (unary or binary), *, /, ** Number-valued.
. String concatenation
systime (seconds since epoch), urand Functions of no arguments returning numbers
abs, ceil, cos, exp, floor, log, log10, pow, round, sin, tan Number-to-number functions with one argument
atan2 Number-to-number functions with two arguments
tolower, toupper String-to-string functions with one argument

See also the awk-like built-in variables NF, NR, FNR, FILENUM, and FILENAME as described in the section on put.