5

I am developing a Linux's Bash shell script that extracts data from a text file leaving only the numbers. These are my example parsed data:

3
4
4
5
6
7
8
8
9
11

I would like to create a simple text-mode bar chart like this one, but corresponding to these values:

Bar chart

Details:

  • I need the graphic chart to be vertical.
  • The first numbers should appear on the left, latest on the right.
  • A n (parsed number) characters high column is appropriate for me. So the first bar on the left in my example should be 3 characters high, the second 4, the third 4, the fourth 5, and so on.

More precisely, for this example, something (using the character) like:

         █
         █
        ██ 
       ███
      ████
     █████
    ██████
   ███████
 █████████
██████████
██████████
██████████

Note the 3 characters high for the first (left) column and 11 characters high for the last (right) column.
Same example with $ characters, to make it more readable:

         $
         $
        $$
       $$$
      $$$$
     $$$$$
    $$$$$$
   $$$$$$$
 $$$$$$$$$
$$$$$$$$$$
$$$$$$$$$$
$$$$$$$$$$

The closest I know of is my method for progress bar until now, that I have used in another scripts:

printf "\033[48;5;21m"   # Blue background color
for i in $(seq 1 $n); do printf " "; done   # Create bar using blue spaces

This is: filling each line printing a bar with n spaces. But this bar is horizontal, so it is not appropriate in this case.

I request some core loop example ideas to create this bar chart.

Under the suggestion of user Boardrider, solutions based on any unix-like tools are accepted. Solutions based on scripting languages (like Perl or Python) for the Linux shell are accepted too, as long as they use to be implemented on many devices.

Sopalajo de Arrierez
  • 3,543
  • 4
  • 34
  • 52
  • Are unix-like tools the best for this assignment? Won't a scripting language be a better tool? – boardrider Jun 19 '15 at 10:57
  • Well, @boardrider, I would like to use Bash shell for this case. But if such bar chart printing were difficult, I could consider using another language. – Sopalajo de Arrierez Jun 19 '15 at 11:16
  • I must admit your initial suggestion was good, @boardrider . I have widened the question to allow any Linux shell tool (not only Bash), and even commonly used scripting languages for the shell, like Perl, Python... etc. – Sopalajo de Arrierez Oct 26 '15 at 16:04

5 Answers5

7

Here is a first and naive attempt... It's not a very efficient solution as data are parsed many times, but may it helps. In a way it's the first loop idea suggested by @Walter_A.

#!/bin/sh
#
## building a vertical bar graph of data file
## https://stackoverflow.com/q/30929012
##
## 1. required. Data file with one value per line and nothing else!
## /!\ provide the (relative or absolute) file path, not file content
: ${1:?" Please provide a file name"}
test -e "$1" || { echo "Sorry, can't find $1" 1>&2 ; exit 2 ; }
test -r "$1" || { echo "Sorry, can't access $1" 1>&2 ; exit 2 ; }
test -f "$1" || { echo "Sorry, bad format file $1" 1>&2 ; exit 2 ; }
test $( grep -cv '^[0-9][0-9]*$' "$1" 2>/dev/null ) -ne 0 || { echo "Sorry, bad data in $1" 1>&2 ; exit 3 ; }
# setting characters
## 2. optional. Ploting character (default is Dollar sign)
## /!\ for blank color use "\033[48;5;21m \033[0m" or you'll mess...
c_dot="$2"
: ${c_dot:='$'}
## 3. optional. Separator characher (default is Dash sign)
## /!\ as Space is not tested there will be extra characters...
c_sep="$3"
: ${c_sep:='-'}
# init...
len_w=$(wc -l "$1" | cut -d ' ' -f 1 )
l_sep=''
while test "$len_w" -gt 0
do
        l_sep="${l_sep}${c_sep}";
        len_w=$(($len_w-1))
done
unset len_w
# part1: chart
echo ".${c_sep}${l_sep}${c_sep}."
len_h=$(sort -n "$1" | tail -n 1)
nbr_d=${#len_h}
while test "$len_h" -gt 0
do
        printf '| '
        for a_val in $(cat "$1")
        do
                test "$a_val" -ge "$len_h" && printf "$c_dot" || printf ' '
        done
        echo ' |'
        len_h=$(($len_h-1))
done
unset len_h
# part2: legend
echo "|${c_sep}${l_sep}${c_sep}|"
while test "$nbr_d" -gt 0
do
        printf '| '
        for a_val in $(cat "$1")
        do
                printf "%1s" $(echo "$a_val" | cut -c "$nbr_d")
        done
        echo ' |'
        nbr_d=$(($nbr_d-1))
done
unset nbr_d
# end
echo "'${c_sep}${l_sep}${c_sep}'"
unset c_sep
exit 0

EDIT 1: Here is a rework on the script. It correct separators handling (just try with ' ' or '|' as third argument to see), but it may look less readable as I use arguments number instead of a additional variable.

EDIT 2: It also deals with negative integers... and you may change the ground (5th parameter)

#!/bin/sh
#
## building a vertical bar graph of data file
## https://stackoverflow.com/q/30929012
##
## 1. required. Data file with one value per line and nothing else!
## /!\ provide the (relative or absolute) file path, not file content
: ${1:?" Please provide a file name"}
[ -e "$1" ] || { echo "Sorry, can't find $1" 1>&2 ; exit 2 ; }
[ -r "$1" ] || { echo "Sorry, can't access $1" 1>&2 ; exit 2 ; }
[ -f "$1" ] || { echo "Sorry, bad format file $1" 1>&2 ; exit 2 ; }
[ $( grep -cv '^[-0-9][0-9]*$' "$1" 2>/dev/null ) -ne 0 ] || { echo "Sorry, bad data in $1" 1>&2 ; exit 3 ; }
## /!\ following parameters should result to a single character
## /!\ for blank color use "\033[48;5;21m \033[0m" or you'll mess...
## 2. optional. Ploting character (default is Dollar sign)
## 3. optional. Horizontal border characher (default is Dash sign)
## 4. optional. Columns separator characher (default is Pipe sign)
## (!) however, when no arg provided the graph is just framed in a table
## 5. optional. Ground level integer value (default is Zero)
test "${5:-0}" -eq "${5:-0}" 2>/dev/null || { echo "oops, bad parameter $5" 1>&2 ; exit 3 ; }
# init...
_long=$(wc -l < "$1" ) # width : number of data/lines in file
if [ -n "$4" ]
then
        _long=$((_long*2-3))
fi
_line=''
while [ "$_long" -gt 0 ]
do
        _line="${_line}${3:--}"
        _long=$((_long-1))
done
unset _long
_from=$(sort -n "$1" | tail -n 1 ) # max int
_stop=$(sort -n "$1" | head -n 1 ) # min int

This rework comes in two flavors. The first produces an output like the previous one.

# begin
echo "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
        while [ $_from -gt ${5:-0} ]
        do
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -ge $_from ]
                        then
                                printf "${2:-$}$4"
                        else
                                printf " $4"
                        fi
                done
                echo " ${4:-|}"
                _from=$((_from-1))
        done
        echo "${4-|}${3:--}${_line}${3:--}${4-|}"
fi
unset _from
# center/legend
_long=$(wc -L < "$1" ) # height : number of chararcters in longuest line...
while [ $_long -ge 0 ]
do
        printf "${4:-| }"
        for _cint in $(cat "$1" )
        do
                printf "%1s$4" $(echo "$_cint" | cut -c "$_long" )
        done
        echo " ${4:-|}"
        _long=$((_long-1))
done
unset _long
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
        _from=${5:-0}
        echo "${4-|}${3:--}${_line}${3:--}${4-|}"
        while [ $_from -gt $_stop ]
        do
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -lt $_from ]
                        then
                                printf "${2:-$}$4"
                        else
                                printf " $4"
                        fi
                done
                echo " ${4:-|}"
                _from=$((_from-1))
        done
fi
unset _stop
# end
echo "${4-'}${3:--}${_line}${3:--}${4-'}"
exit 0

Notice : There're two checks in order to avoid extra loop when all values are positive (above the ground) or negative (bellow the ground) ! Well, maybe I should always put the "center/legend" part at the end? It looks a bit ugly when there're both positive and negative values first, and when only negative integers it looks strange that labels don't read in the opposite and have unpleasant minus sign.
Also notice that wc -L is not POSIX... ...so another loop may be needed.

Here is another variant with legend number in the right size instead of the bottom. Doing so, I save an extra loop but I don't really like the output (I prefer values on the left rather than the right side, but it's a taste isn't it ?)

# begin
printf "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
        echo ""
        while [ $_from -gt ${5:-0} ]
        do
                _ctxt=''
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -ge $_from ]
                        then
                                printf "${2:-$}$4"
                        else
                                printf " $4"
                        fi
                        if [ $_cint -eq $_from ]
                        then
                                _ctxt="_ $_from"
                        fi
                done
                echo " ${4:-}${_ctxt}"
                _from=$((_from-1))
        done
        _from=$((_from+1))
else
        echo "_ ${1}"
fi
# center/ground
if [ $_stop -lt ${5:-0} ] && [ $_from -gt ${5:-0} ]
then
        echo "${4-|}${3:--}${_line}${3:--}${4-|}_ ${1}"
fi
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
        _from=${5:-0}
        while [ $_from -gt $_stop ]
        do
                _ctxt=''
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -lt $_from ]
                        then
                                printf "${2:-$}$4"
                        else
                                printf " $4"
                        fi
                        if [ $_cint -eq $((_from-1)) ]
                        then
                                _ctxt="_ $_cint"
                        fi
                done
                echo " ${4:-|}${_ctxt}"
                _from=$((_from-1))
        done
fi
# end
unset _from
printf "${4-'}${3:--}${_line}${3:--}${4-'}"
if [ $_stop -lt ${5:-0} ]
then
        echo ""
else
        echo "_ ${1}"
fi
unset _stop
exit 0

EDIT 3: There're some extra checks so an extra ground line isn't added when there's only positive or negative numbers.

Finally, i think the final solution is a mix of both, where value are displayed on the side and the position of value in the center. Then it's more close to GNU Plot's output.

# init...
_long=$(wc -l < "$1" )
if [ -n "$4" ]
then
        _long=$((_long*2-3))
fi
_line=''
while [ $_long -gt 0 ]
do
        _line="${_line}${3:--}"
        _long=$((_long-1))
done
unset _long
_from=$(sort -n "$1" | tail -n 1 ) # max int
_stop=$(sort -n "$1" | head -n 1 ) # min int
# begin
echo "${4-.}${3:--}${_line}${3:--}${4-.}"
# upper/positive
if [ $_from -gt ${5:-0} ]
then
        while [ $_from -gt ${5:-0} ]
        do
                _ctxt=''
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -ge $_from ]
                        then
                                printf "${2:-$}$4"
                        else
                                printf " $4"
                        fi
                        if [ $_cint -eq $_from ]
                        then
                                _ctxt="_ $_from"
                        fi
                done
                echo " ${4:-|}$_ctxt"
                _from=$((_from-1))
        done
        echo "${4-|}${3:--}${_line}${3:--}${4-|}"
fi
# center/ground
_size=$(wc -l < "$1" ) # width : number of data/lines in file
##_long=${#_size} # height : number of chararcters in long
#_long=1
##while [ $_long -gt 0 ]
#while [ $_long -le ${#_size} ]
#do
       #_rank=1
       #printf "${4:-| }"
       #while [ $_rank -le $_size ]
       #do
               #printf "%1s$4" $( printf "%0${#_size}d" $_rank  | cut -c $_long )
               #_rank=$((_rank+1))
       #done
       #printf " ${4:-|}"
       ##_long=$((_long-1))
       #_long=$((_long+1))
       ##if [ $_long -eq 0 ]
       #if [ $_long -eq ${#_size} ]
       #then
               #printf "_ ${1}"
       #fi
       #echo ''
#done
_rank=1
printf "${4:-| }"
while [ $_rank -le $_size ]
do
        printf "%1s$4" $( expr "$_rank" : '.*\(.\)$' )
        _rank=$((_rank+1))
done
echo " ${4:-|}_ ${1}"
# lower/negative
if [ $_stop -lt ${5:-0} ]
then
        echo "${4-|}${3:--}${_line}${3:--}${4-|}"
        while [ $_from -gt $_stop ]
        do
                _ctxt=''
                printf "${4:-| }"
                for _cint in $(cat "$1" )
                do
                        if [ $_cint -lt $_from ]
                        then
                                printf "${2:-$}${4}"
                        else
                                printf " $4"
                        fi
                        if [ $_cint -eq $((_from-1)) ]
                        then
                                _ctxt="_ $_cint"
                        fi
                done
                echo " ${4:-|}$_ctxt"
                _from=$((_from-1))
        done
fi
unset _from
unset _stop
# end
echo "${4-'}${3:--}${_line}${3:--}${4-'}"
exit 0

A last improvement would be the ability to scale...

Community
  • 1
  • 1
gildux
  • 448
  • 6
  • 12
  • Fancy and working! Thanks you, Gildux. Now that I have a pure (or nearly) Bash solution, I have decided to widen the question to allow any Linux shell tool, or even scripting languages, as requested in the comments. – Sopalajo de Arrierez Oct 26 '15 at 16:09
  • @sopalajo-de-arrierez It's a POSIX solution (tested with DASh under Debian but BASh when called as "sh" non-interactively is mostly POSIX-compliant) What do you mean by "allow any Linux shell tool, or even scripting languages"? – gildux Oct 27 '15 at 13:13
  • I mean that I have found usual for shell questions to give answers valid for any shell, for specific shell(s), for tools commonly included in many distros (or at least the most popular ones, like Ubuntu or Debian), for open source tools that must be downloaded (or compiled), for widespread scripting languages that seem to be conceived as POSIX enhancements on many Linux (like Perl or Python) and even (not so usual) for payment tools that work in the shell. I agree with that behavior of Unix Stack Exchange. I only specified BASH because when just writing `shell` some people sometimes ask. – Sopalajo de Arrierez Oct 28 '15 at 22:37
  • Respecting to the selection of the accepted (the "best") answer, it is to a ambiguous matter. I would prefer POSIX compliant, as long as they are the more adaptable. But sometimes single one-line solutions are very practical. I think there is no conventions about that on Stack Exchange forums, but I would say... who bothers? We are here to learn and to build a Wiki Catalog, not to obtain reputation points. – Sopalajo de Arrierez Oct 28 '15 at 22:41
  • 1
    As we are here to learn and build a Wiki Catalog, and also because I have the need too, I reworked on the initial answer in order to make a more robust script and a bit more adaptable tool. That makes me go in some other directions I want to share, so I edited the answer to put all 4 cousin scripts : people may then test and improve. – gildux Nov 13 '15 at 16:17
  • Feedback on your nifty work: problems when the numbers file has a blank line (some editors automatically add it at the end). – Sopalajo de Arrierez Jan 10 '16 at 22:32
  • Marked as (deserved) accepted answer: the multiple options and clean code will remain as a good reference help. Congratulations. – Sopalajo de Arrierez Jan 11 '16 at 01:51
3

Methinks it can be a bit simpler...

#!/bin/bash

# Asume the data is in a textfile "/tmp/testdata.txt". One value per line.

MAXVALUE=$( sort -nr /tmp/testdata.txt | head -n1 )     # get the highest value
CHARTHEIGHT=$MAXVALUE                                   # use it for height of chart 
                                                        # (can be other value)
CHARTLINE=$CHARTHEIGHT                                  # variable used to parse the lines

while [ $CHARTLINE -gt 0 ]; do                          # start the first line
    (( CHARTLINE-- ))                                    
    REDUCTION=$(( $MAXVALUE*$CHARTLINE/$CHARTHEIGHT ))  # subtract this from the VALUE
    while read VALUE; do
        VALUE=$(( $VALUE-$REDUCTION ))
        if [ $VALUE -le 0 ]; then                       # check new VALUE
             echo -n "    " 
        else
             echo -n "▓▓▓ "
        fi
    done < /tmp/testdata.txt
    echo
done
echo
exit

This script will parse the data every line, reduces the read value and checks if there's something left. If so, display a block; if not, display a space. Repeat every line with different REDUCTION value. The script can be expanded to included a legend, colours, half/quarter blocks, etc...

Apart from SORT and HEAD it's all in BASH commands

2

You can install a dedicated tool for ploting... I only know GNU-Plot, but it's big (with many dependencies including ImageMagick)

root@localhost: # apt-get install gnuplot-nox
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  fontconfig fontconfig-config fonts-droid fonts-liberation ghostscript groff
  gsfonts hicolor-icon-theme imagemagick imagemagick-common libcairo2 libcroco3
  libcupsimage2 libdatrie1 libdjvulibre-text libdjvulibre21 libexiv2-12 libffi5
  libfontconfig1 libgd2-noxpm libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-common
  libglib2.0-0 libglib2.0-data libgs9 libgs9-common libice6 libijs-0.35
  libilmbase6 libjasper1 libjbig0 libjbig2dec0 libjpeg8 liblcms1 liblcms2-2
  liblensfun-data liblensfun0 liblqr-1-0 libltdl7 liblua5.1-0 libmagickcore5
  libmagickcore5-extra libmagickwand5 libnetpbm10 libopenexr6 libpango1.0-0
  libpaper-utils libpaper1 libpixman-1-0 libpng12-0 librsvg2-2 librsvg2-common
  libsm6 libthai-data libthai0 libtiff4 libwmf0.2-7 libxaw7 libxcb-render0
  libxcb-shm0 libxft2 libxmu6 libxpm4 libxrender1 libxt6 netpbm poppler-data
  psutils shared-mime-info ttf-dejavu-core ufraw-batch x11-common
Suggested packages:
  ghostscript-cups ghostscript-x hpijs gnuplot-doc imagemagick-doc autotrace
  cups-bsd lpr lprng curl enscript ffmpeg gimp gnuplot grads hp2xx html2ps
  libwmf-bin mplayer povray radiance sane-utils texlive-base-bin transfig
  xdg-utils exiv2 libgd-tools libjasper-runtime liblcms-utils liblcms2-utils
  ttf-baekmuk ttf-arphic-gbsn00lp ttf-arphic-bsmi00lp ttf-arphic-gkai00mp
  ttf-arphic-bkai00mp librsvg2-bin poppler-utils fonts-japanese-mincho
  fonts-ipafont-mincho fonts-japanese-gothic fonts-ipafont-gothic
  fonts-arphic-ukai fonts-arphic-uming fonts-unfonts-core ufraw
The following NEW packages will be installed:
  fontconfig fontconfig-config fonts-droid fonts-liberation ghostscript
  gnuplot-nox groff gsfonts hicolor-icon-theme imagemagick imagemagick-common
  libcairo2 libcroco3 libcupsimage2 libdatrie1 libdjvulibre-text libdjvulibre21
  libexiv2-12 libffi5 libfontconfig1 libgd2-noxpm libgdk-pixbuf2.0-0
  libgdk-pixbuf2.0-common libglib2.0-0 libglib2.0-data libgs9 libgs9-common
  libice6 libijs-0.35 libilmbase6 libjasper1 libjbig0 libjbig2dec0 libjpeg8
  liblcms1 liblcms2-2 liblensfun-data liblensfun0 liblqr-1-0 libltdl7 liblua5.1-0
  libmagickcore5 libmagickcore5-extra libmagickwand5 libnetpbm10 libopenexr6
  libpango1.0-0 libpaper-utils libpaper1 libpixman-1-0 libpng12-0 librsvg2-2
  librsvg2-common libsm6 libthai-data libthai0 libtiff4 libwmf0.2-7 libxaw7
  libxcb-render0 libxcb-shm0 libxft2 libxmu6 libxpm4 libxrender1 libxt6 netpbm
  poppler-data psutils shared-mime-info ttf-dejavu-core ufraw-batch x11-common
0 upgraded, 73 newly installed, 0 to remove and 0 not upgraded.
Need to get 38.3 MB of archives.
After this operation, 111 MB of additional disk space will be used.
Do you want to continue [Y/n]?

(asking for "gnuplot" provide the same packages plus "gnuplot-nox") Once installed, I check interactively with a data file just called data:

Terminal type set to 'unknown'
gnuplot>  set term dumb
Terminal type set to 'dumb'
Options are 'feed size 79, 24'
gnuplot> plot data
undefined variable: data
gnuplot> plot "data"
gnuplot> # nice ASCII-chart not shown here, curve of "A"
gnuplot> set style data histogram
gnuplot> plot "data"
gnuplot> # nice ASCII-chart not shown here, bars of "**"
gnuplot> quit

For a quick start, look at this lowrank.net page then histograms demo
and finaly, usage here plus here to script the beast
For example :

#!/bin/sh
#
_max=$(sort -n "$1" | tail -n 1)
_min=$(sort -n "$1" | head -n 1)
_nbr=$(wc -l < "$1" )
gnuplot << EOF
set terminal dumb ${COLUMNS:-$(tput cols)},${LINES:-$(tput lines)}
set style data histogram
set xrange[-1:$(_nbr+1)]
set yrange[$(_min-3):$(_max+2)]
set xlabel "something to display below horizontal axis"
plot "$1" title "a nice title in the corner instead of filename"
EOF

Just change options to output a true graphic into a file.
And when there are very few options to set :

#!/bin/sh
#
gnuplot -e "set terminal dumb; set style data histogram; plot '$1' "

It may look overkill compared to shell script if there are only few data to plot. But using such a tool becomes very usufull for a large amount of data (it runs faster) or with some variety (GNUPlot escapes blank lines, plots both positive and negative integers and decimals, used multi-fields files, merge many files or columns in the same graph)
Finally, they're some interesting front-end to ease some use cases

  • eplot is a Ruby wrapper to pipe into it.
  • feedgnuplot is a Perl front-end that may look easier.
  • termplotlib, previously known as asciiplotlib, is a Python library over it.

EDIT: By default it uses screen size minus margin...

gildux
  • 448
  • 6
  • 12
  • A very complete solution. How sad it requires X-Windows. Thanks anyway, many people could find it useful. – Sopalajo de Arrierez Nov 09 '15 at 04:09
  • 1
    No, no... Some X libs are requiered (those related to fonts) because they are used by some image formats as GNU Plot can output to almost any format (I think it uses Image Magic to perform conversions) I test it in a box without X windowing system and there was no more X after that install (gnuplot-nox for Debian) – gildux Nov 10 '15 at 12:31
0

loop idea 1: Search for the highest number and remember nr of lines.
Start with value=the highest number, end check all values -ge ${value}. These will be filled, other spaces. Next line you use (( value = value - 1 )).
Not very efficient, you will walk through the parsed data lot of times.

loop idea 2: Create strings like "xxx" and "xxxxxxxx" from your data (and rememeber largest value). You have your chart horizantally) Usee printf formatting for adding spaces to each line (you have a file with all lines the same length) Search a way to pivot your file.

loop idea 3: When you have k values with m as highest value, first create a file with m lines of k sequential numbers (1 2 3 ...) and end the line with a space.
Loop through the values and replace the numbers with 'x' on the right place. For value 6 in line 3 this would be something like

(( replace_from = m - 5 ))
sed -i ${replace_from}',$ s/ 6 / x /g' myfile

After the loop replace all numbers by spaces.

Walter A
  • 19,067
  • 2
  • 23
  • 43
0

There're many graphing libraries for Python. Python plotting libraries lists most of them. However I think they are X oriented... But some people wrote alternative solutions for console/terminal. I found (initially two, updated with others):

  • pysparklines and its elder spark to graph small histogram of input using Unicode characters (so it's nice but limited, as it's a single line, and renders better under X or a console with UTF-8 font)
  • bashplotlib - despite its name is a pythonic collection that can draw histograms and scatters in pure terminal/console in a similar way to Gnuplot.
  • plotext can draw histograms and scatters in terminal.
  • termgraph can draw histograms and heatmap, plus has ability to use colours (with colorama) or custom ticks.
  • YouPlot (with command uplot and graph type as subcommand) is a new challenger in Ruby…

Update February 2023: they're some interesting libraries you can use interactively or within your Python code.

  • terminalplot and termplot are very simple and ASCII term oriented, with no dependency. They're easy to use too. But termplot does only vertical bars (like the images in the question.)
  • uniplot is a more capable because of heavy use of Unicode (hence better under X with UTF-8 font) and NumPy as sole dependency.
  • termplotlib seems to be similar to the previous but with no Unicode related. It also depends on NumPy and gunplots (it's a big/heavy front-end then.) It has a nice cousin, termtables for tables, but that's another topic.
  • plotext also claims no dependency and is very capable. However I suspect it needs an advanced terminal, not a dumb ASCII one, for some advanced rendering. Anyway, it's similar to mathplotlib which in-opposition is X oriented (workaround may be in use of mathplotlib-backend-kitty or mathplotlib-sixel for example.)
  • plotille is a generic graphing similar to gunplot or mathplotlib, but internally build with canvas available for any nice braille-dot-art too. Dependencies are: NumPy, Pendulum, Mock, Pillow, Flake8.
gildux
  • 448
  • 6
  • 12
  • They both seem promising, Gildux. I suggest for you to divide them as two different answers. And, according to rules, you should add some simple installation procedure (I have not been able to find it for `pysparklines`) and/or usage info/example. – Sopalajo de Arrierez Nov 10 '15 at 16:29
  • For [pysparklines](https://pypi.python.org/pypi/pysparklines) I just used `pip install pysparklines` The command is `sparkline` follow by the list of integers (as they are in a `data` file i use `sparkline < data` As I mentionned, the result is a single line with unicode characters (in my box without X, some characters are square boxes) – gildux Nov 13 '15 at 16:39
  • For [bashplotlib](https://pypi.python.org/pypi/bashplotlib) I also installed using `pip install bashplotlib` The commands are `hist` and `scatter` but I couldn't get it working: `ImportError: No module named bashplotlib.histogram` Ok, after googling, [it should be installed from source](https://github.com/glamp/bashplotlib/issues/30) Then, I went to the [project home](https://github.com/glamp/bashplotlib) and download the source zip... After than : `pip unstall bashplotlib; unzip bashplotlib-master.zip; cd bashplotlib-master; python setup.py install` and I was able to try: `hist --file data` – gildux Nov 13 '15 at 17:15
  • Thanks for the info, Gildux. Indeed, the `spark` command does not work without X Windows. – Sopalajo de Arrierez Nov 13 '15 at 20:35
  • The `hist` tool on `bashplotlib` seems to be a histogram creator, rather than a bar chart plotter. – Sopalajo de Arrierez Nov 13 '15 at 20:59