Help language development. Donate to The Perl Foundation

Text::Plot zef:antononcube last updated on 2022-08-04

42a660e7668ab7657daddf10aa8df0efc14bc218/

Raku Text::Plot

This repository has a Raku package for textual (terminal) plots.

Here is the list of functions:

Currently only text-list-plot is implemented.

It would be nice to also have the functions:

But that would require dependency on a certain statistical package. (I think it is best to keep this package simple.)


Installation

From zef-ecosystem:

zef install Text::Plot

From GitHub:

zef install https://github.com/antononcube/Raku-Text-Plot.git

Usage examples

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    => -0.9954833520919175 | Min    => 5.889337210606804  |
# | 1st-Qu => 2.4618033540669657  | 1st-Qu => 10.262915243722706 |
# | Mean   => 3.7969073471031507  | Mean   => 12.416158189508215 |
# | Median => 3.4723152968399544  | Median => 12.547803843669296 |
# | 3rd-Qu => 5.295629015632202   | 3rd-Qu => 14.471747043316954 |
# | Max    => 8.02912075714216    | Max    => 19.903020387445054 |
# +-------------------------------+------------------------------+
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.


Command Line Interface (CLI)

The package function text-list-plot can be used through the corresponding CLI:

> text-list-plot --help
# Usage:
#   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>] [<points> ...] -- Makes textual (terminal) plots.
#   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>] <words> -- 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 

Here is an example of 2D points call:

text-list-plot "22,32 10,39 13,32 14,20"

Here is an example pipeline:

> raku -e 'say (^1000).roll(21)' | text-list-plot
# +---+------------+-----------+------------+------------+---+          
# |                                                          |          
# |     *                                                    |          
# +                *                        *            *   +  800.00  
# |                            *                    *        |          
# |                     *                         *          |          
# +                                                          +  600.00  
# |                          *                               |          
# |          *                       *                       |          
# +                               *    *                     +  400.00  
# |        *         *                                       |          
# |                       *               *            *     |          
# +   *         *                                            +  200.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.)


Implementation notes


TODO


References

[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.