This repository has a Raku package for textual (terminal) plots.
Here is the list of functions:
-
text-list-plot
-
text-plot
-
text-bar-chart
-
text-pareto-principle-plot
Currently only text-list-plot
and text-pareto-principle-plot
are implemented.
It would be nice to also have the functions:
-
text-density-plot
-
text-box-plot
But that would require dependency on a certain statistical package. (I think it is best to keep this package simple.)
From zef-ecosystem:
zef install Text::Plot
From GitHub:
zef install https://github.com/antononcube/Raku-Text-Plot.git
Simple plot with y-values only:
use Text::Plot;
say text-list-plot((^30)>>.sqrt);
# +---+-------+--------+--------+--------+--------+--------+-+
# | |
# + * * * ** + 5.00
# | * * * ** |
# + * * ** + 4.00
# | * * ** |
# + ** * + 3.00
# | * * |
# + ** * + 2.00
# | * |
# + * * + 1.00
# | |
# + * + 0.00
# | |
# +---+-------+--------+--------+--------+--------+--------+-+
# 0.00 5.00 10.00 15.00 20.00 25.00 30.00
Plot using both x- and y-values, and with specified axes labels, y-tick-labels format, and plot width, height, and title:
my @xs = (0, 0.2 ... 5);
say text-list-plot(@xs, @xs>>.sin,
x-label => 'x-points',
y-label => 'value',
y-tick-labels-format => '%10.2e',
width => 80,
height => 18,
title => 'SINE PLOT');
# SINE PLOT
# +---+-------------+-------------+-------------+-------------+-------------+----+
# | |
# + * * * * * + 1.00e+00
# | * * |
# | * * |
# + * * + 5.00e-01
# | * * | v
# | * | a
# | * | l
# + * * + 0.00e+00 u
# | * | e
# | |
# + * + -5.00e-01
# | * |
# | * * |
# + * * * * + -1.00e+00
# | |
# +---+-------------+-------------+-------------+-------------+-------------+----+
# 0.00 1.00 2.00 3.00 4.00 5.00
# x-points
Smallish plot with custom point character spec:
my @xs = (0, 0.05 ... 10);
say text-list-plot(@xs, -1 <<*>> @xs>>.sqrt,
point-char => '·',
width => 40,
height => 12);
# +--+-----+------+------+------+-----+--+
# + · + 0.00
# | · |
# + ··· + -0.50
# + ··· + -1.00
# + ···· + -1.50
# | ······ |
# + ······ + -2.00
# + ········ + -2.50
# + ········ + -3.00
# + · + -3.50
# +--+-----+------+------+------+-----+--+
# 0.00 2.00 4.00 6.00 8.00 10.00
Plot a list of two-element lists:
say text-list-plot((^@xs.elems Z @xs>>.cos).List, title => 'Some list of lists'),
# Some list of lists
# +---+------------+-----------+------------+------------+---+
# | |
# + *** ******* + 1.00
# | ** ** *** |
# + ** *** ** + 0.50
# | ** ** ** |
# | ** * ** |
# + ** * * + 0.00
# | ** * * |
# | ** * * |
# + ** * ** + -0.50
# | *** ** ** |
# + ******* ******* + -1.00
# | |
# +---+------------+-----------+------------+------------+---+
# 0.00 50.00 100.00 150.00 200.00
Here is a more complicated example using a randomly generated dataset, [AAp1, AAp2]:
use Data::Generators;
use Data::Summarizers;
my @dsRand = random-tabular-dataset(70, <x y>,
generators => [{ random-variate(NormalDistribution.new(4, 2), $_) },
{ random-variate(NormalDistribution.new(12, 3), $_) }]);
records-summary(@dsRand);
# +-------------------------------+------------------------------+
# | x | y |
# +-------------------------------+------------------------------+
# | Min => -1.9315282286837414 | Min => 5.408529291403756 |
# | 1st-Qu => 2.8232810235358086 | 1st-Qu => 9.806219961394248 |
# | Mean => 3.9671188479758186 | Mean => 11.742380660644757 |
# | Median => 4.173600521820246 | Median => 11.586859774445358 |
# | 3rd-Qu => 5.443198351747228 | 3rd-Qu => 13.815276322178805 |
# | Max => 7.506965375963047 | Max => 19.501133858154923 |
# +-------------------------------+------------------------------+
text-list-plot(@dsRand.map({ $_<x y> })>>.List,
x-limit => (-2, 10), y-limit => (0, 25),
title => 'Random Normal distribution variates')
# Random Normal distribution variates
# ++---------+--------+---------+--------+---------+--------++
# + + 25.00
# | |
# + + 20.00
# | * ** |
# | * * * * |
# + * * * * ** **** * * * + 15.00
# | * * * *** * * *** |
# +* * ** * *** ** * * ** + 10.00
# | * * ** * ** |
# | * * * * |
# + + 5.00
# | |
# + + 0.00
# ++---------+--------+---------+--------+---------+--------++
# -2.00 0.00 2.00 4.00 6.00 8.00 10.00
Remark: The function text-list-plot
has camel case aliases for the multi-word named arguments.
For example, xLimit
for x-limit
and xTickLabelsFormat
for x-tick-labels-format
.
Here is an example of a multi-list plot:
say text-list-plot([([1,1], [2,5], [3,2], [4,5]),
([1,1], [3,3], [3,2]),
([1,3], [2,1], [5,2])], point-char => Whatever);
# +---+------------+-----------+------------+------------+---+
# | |
# + * * + 5.00
# | |
# + + 4.00
# | |
# | |
# + ▽ □ + 3.00
# | |
# | |
# + □ ▽ + 2.00
# | |
# + □ ▽ + 1.00
# | |
# +---+------------+-----------+------------+------------+---+
# 1.00 2.00 3.00 4.00 5.00
Remark: Note that the points [1,1]
and [3,2]
of the second list overlay the same points of first list.
Assume we have a data vector with all numeric or with all string elements.
The adherence of the data vector to the Pareto principle can be easily verified with the plots of
text-pareto-principle-plot
.
Here is an example with a numeric vector:
text-pareto-principle-plot( random-real(10, 300), title => 'Random reals')
# Random reals
# 0.00 0.17 0.33 0.50 0.67 0.83 1.00
# +---+-------+--------+--------+-------+--------+-------+---+
# | |
# + **************** + 1.00
# | ******* |
# + ***** + 0.80
# | **** |
# + ***** + 0.60
# | **** |
# + **** + 0.40
# | **** |
# + *** + 0.20
# | *** |
# | *** |
# + + 0.00
# +---+-------+--------+--------+-------+--------+-------+---+
# 0.00 50.00 100.00 150.00 200.00 250.00 300.00
Here is an example with a vector of strings:
text-pareto-principle-plot( random-pet-name(500), title => 'Random pet names')
# Random pet names
# 0.00 0.24 0.48 0.73 0.97
# +---+-----------+------------+-----------+------------+----+
# | |
# + ****** + 1.00
# | ******* |
# + ****** + 0.80
# | ******* |
# + ******* + 0.60
# | ****** |
# + ****** + 0.40
# | ******* |
# + **** + 0.20
# | *** |
# | ** |
# + + 0.00
# +---+-----------+------------+-----------+------------+----+
# 0.00 100.00 200.00 300.00 400.00
The package function text-list-plot
can be used through the corresponding CLI:
text-list-plot --help
# Usage:
# text-list-plot [<points> ...] [-p|--point-char=<Str>] [-w|--width[=Int]] [-h|--height[=Int]] [-t|--title=<Str>] [--xLabel|--x-label=<Str>] [--yLabel|--y-label=<Str>] [--xTickLabelsFormat|--x-tick-labels-format=<Str>] [--yTickLabelsFormat|--y-tick-labels-format=<Str>] -- Makes textual (terminal) plots.
# text-list-plot <words> [-p|--point-char=<Str>] [-w|--width[=Int]] [-h|--height[=Int]] [-t|--title=<Str>] [--xLabel|--x-label=<Str>] [--yLabel|--y-label=<Str>] [--xTickLabelsFormat|--x-tick-labels-format=<Str>] [--yTickLabelsFormat|--y-tick-labels-format=<Str>] -- Makes textual (terminal) plots by splitting a string of data points.
# text-list-plot [-p|--point-char=<Str>] [-w|--width[=Int]] [-h|--height[=Int]] [-t|--title=<Str>] [--xLabel|--x-label=<Str>] [--yLabel|--y-label=<Str>] [--xTickLabelsFormat|--x-tick-labels-format=<Str>] [--yTickLabelsFormat|--y-tick-labels-format=<Str>] -- Makes textual (terminal) plots from pipeline input
#
# [<points> ...] Data points.
# -p|--point-char=<Str> Plot points character. [default: '*']
# -w|--width[=Int] Width of the plot. (-1 for Whatever.) [default: -1]
# -h|--height[=Int] Height of the plot. (-1 for Whatever.) [default: -1]
# -t|--title=<Str> Title of the plot. [default: '']
# --xLabel|--x-label=<Str> Label of the X-axis. If Whatever, then no label is placed. [default: '']
# --yLabel|--y-label=<Str> Label of the Y-axis. If Whatever, then no label is placed. [default: '']
# --xTickLabelsFormat|--x-tick-labels-format=<Str> X-axis tick labels format. [default: '']
# --yTickLabelsFormat|--y-tick-labels-format=<Str> Y-axis tick labels format. [default: '']
# <words> String with data points.
Here is an example of a simple, y-axis values only call:
text-list-plot 33 12 21 10 3 4
# +-----+------------------+-------------------+------------------+------------------+-------------------+-----+
# + + 35.00
# | * |
# | |
# + + 30.00
# | |
# | |
# | |
# + + 25.00
# | |
# | |
# | * |
# + + 20.00
# | |
# | |
# | |
# + + 15.00
# | |
# | * |
# | |
# + * + 10.00
# | |
# | |
# + + 5.00
# | * |
# | * |
# | |
# +-----+------------------+-------------------+------------------+------------------+-------------------+-----+
# 0.00 1.00 2.00 3.00 4.00 5.00
Here is an example of 2D points call:
text-list-plot "22,32 10,39 13,32 14,20"
# +-----+---------------+---------------+---------------+----------------+---------------+---------------+-----+
# + + 40.00
# | * |
# | |
# | |
# | |
# | |
# + + 35.00
# | |
# | |
# | |
# | * * |
# | |
# + + 30.00
# | |
# | |
# | |
# | |
# | |
# + + 25.00
# | |
# | |
# | |
# | |
# | |
# + * + 20.00
# | |
# +-----+---------------+---------------+---------------+----------------+---------------+---------------+-----+
# 10.00 12.00 14.00 16.00 18.00 20.00 22.00
Here is an example pipeline:
raku -e 'say (^1000).roll(21)' | text-list-plot
# +---+----------+-----------+-----------+-----------+-------+
# | |
# + * + 800.00
# | * * * |
# | * |
# + + 600.00
# | * * |
# + * * * * + 400.00
# | * * * * * * * * |
# | * |
# + * + 200.00
# | |
# + * * + 0.00
# | |
# +---+----------+-----------+-----------+-----------+-------+
# 0.00 5.00 10.00 15.00 20.00
Remark: Attempt is made plot's width and height are determined automatically, using terminal's number of columns and
lines. If that fails width=60
is used. In the pipeline example above text-list-plot
fails to automatically determine
the width and height. (The other example do succeed.)
-
The package functions and their signatures design are easy to come up with, but it is very helpful to have a "good example" to follow.
-
I consider the R-package "txtplot", [BB1], to be such good example.
-
There are at least three Python packages for text plots, but only tried them out once. None was as complete and "nice" as the R-package "txtplot".
-
-
The points and ticks are rescaled with a version of the Mathematica-function
Rescale
. -
The axes ticks are computed with a version of the R-function
pretty
.
-
Plotting a list of two-element lists.
-
Optional tick labels format specs.
-
CLI design and implementation.
-
Make use kebab-case for named arguments and make corresponding camel-case aliases.
-
Multi-list plot support.
-
Plot title.
-
Proper respect of width and height.
- Currently, the width and height are for the plot frame -- title, axes- and tick labels are "extra."
-
Make the axes ticks to be on the left.
-
It was just much easier to put them on the right.
-
BTW, this is probably a bug -- the width of the "total plot" is larger than the specified.
-
-
Optional placement of tick values.
-
text-pareto-principle-plot
-
text-plot
- Easy to implement inlined with
text-plot
, but it might give a simpler interface.
- Easy to implement inlined with
-
text-bar-chart
-
text-histogram
[AAp0] Anton Antonov, Text::Plot Raku package, (2022), GitHub/antononcube.
[AAp1] Anton Antonov, Data::Generators Raku package, (2021), GitHub/antononcube.
[AAp2] Anton Antonov, Data::Summarizers Raku package, (2021), GitHub/antononcube.
[BB1] Bjoern Bornkamp, txtplot R package, (CRAN), (2020), GitHub/bbnkmp.