Skip to content
Prev Previous commit
add barplot
  • Loading branch information
TrungNT committed Jan 17, 2016
commit 40ff90b03df563dc69267630454f7935f24a381d
193 changes: 193 additions & 0 deletions bashplotlib/barplot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
# -*- coding: utf-8 -*-

"""
Plotting terminal based barplots
"""

from .utils.helpers import *
from .histogram import calc_bins, read_numbers

def plot_bar(f, height=20.0, bincount=None, binwidth=None, pch="o",
colour="default", title="", xlab=None, showSummary=False,
regular=False, return_str=False):
''' Plot bar.

Parameters
----------
f : list(number), numpy.ndarray, str(filepath)
input array
height : float
the height of the histogram in # of lines
bincount : int
number of bins in the histogram
binwidth : int
width of bins in the histogram
pch : str
shape of the bars in the plot, e.g 'o'
colour : str
white,aqua,pink,blue,yellow,green,red,grey,black,default,ENDC
title : str
title at the top of the plot, None = no title
xlab : boolean
whether or not to display x-axis labels
showSummary : boolean
whether or not to display a summary
regular : boolean
whether or not to start y-labels at 0
return_str : boolean
return string represent the plot or print it out, default: False

Example
-------
>>> y = np.random.rand(50)
>>> plot_bar(y, bincount=50, colour='red')

>>> 0.971|
>>> 0.923| o o o o
>>> 0.875| o o o o o oo
>>> 0.827| o o o o o o ooo
>>> 0.779| o o o o o o o o ooo
>>> 0.731| o o o o o o o o o ooo
>>> 0.683| oo oo o o o o o o o o o ooo
>>> 0.635| oo oo o oo o o o o o oo o ooo
>>> 0.587| oo oo o oo o ooo o o oo o ooo
>>> 0.539| oo oo o oooo ooo o o oo o ooo o
>>> 0.491| ooo ooo o oooo ooo o o ooo o ooo o
>>> 0.443| ooo ooo oo ooooo oooo o o ooo o ooo o
>>> 0.395| ooo ooo ooooooooo oooo o o ooo o ooo o
>>> 0.347| oooo ooo ooooooooo ooooo o o ooo o ooo o
>>> 0.299| oooo ooo ooooooooo ooooo o o ooo o ooo o
>>> 0.251| oooo ooo ooooooooo ooooo o o ooo o ooo o o
>>> 0.203| oooo ooo ooooooooo ooooo ooo ooo o ooo o o
>>> 0.155| oooo ooo oo ooooooooo ooooo ooo ooo ooooooo oo
>>> 0.107| ooooo ooo oo ooooooooo oooooooooo ooooooooooo ooo
>>> 0.059| ooooo oooooo ooooooooo ooooooooooooooooooooooo ooo
>>> 0.011| oooooooooooooooooooooo ooooooooooooooooooooooooooo
>>> --------------------------------------------------
'''
if pch is None:
pch = "o"

splot = ''
if isinstance(f, str):
f = open(f).readlines()

# ====== Create data ====== #
min_val, max_val = None, None
n, mean, sd = 0.0, 0.0, 0.0

# pick mode and get data
numbers = [i for i in read_numbers(f)]
int_mode = False
if numbers[0].is_integer():
int_mode = True

# rescale big enough to show on bars
min_orig = min(numbers) # original
max_orig = max(numbers)
numbers = [1000 * (i - min_orig) / (max_orig - min_orig + 1e-8) for i in numbers]

# statistics
n = len(numbers)
min_val = min(numbers)
max_val = max(numbers)
mean = sum(numbers) / n
sd = (sum([(mean - i)**2 for i in numbers]) / (n - 1)) ** 0.5

# bins is index
if bincount is not None:
bincount = min(bincount, n)
bins = list(calc_bins(n, 0., n + 0., bincount, binwidth))
bins = [int(i) for i in bins]
hist = dict((i, 0) for i in range(len(bins) - 1))

# hist is the mean value of array with indices within bin
for idx, (i, j) in enumerate(zip(bins, bins[1:])):
arr = numbers[i:j]
hist[idx] = sum(arr) / len(arr) # calculate mean

# ====== Start plot ====== #
min_y, max_y = min(hist.values()), max(hist.values())

start = max(min_y, 1)
stop = max_y + 1

if regular:
start = 1

if height is None:
height = stop - start
if height > 20:
height = 20

ys = list(drange(start, stop, float(stop - start) / height))
ys.reverse()

nlen = max(len(str(min_y)), len(str(max_y))) + 1

if title:
splot += print_return_str(
box_text(title, max(len(hist) * 2, len(title)), nlen),
return_str=return_str)
splot += print_return_str('', return_str=return_str)

used_labs = set()
for y in ys:
if int_mode:
ylab = '%d' % int(y * (max_orig - min_orig + 1e-8) / 1000 + min_orig)
else:
ylab = '%.3f' % float(y * (max_orig - min_orig + 1e-8) / 1000 + min_orig)
if ylab in used_labs:
ylab = ""
else:
used_labs.add(ylab)
ylab = " " * (nlen - len(ylab)) + ylab + "|"

splot += print_return_str(ylab, end=' ', return_str=return_str)

for i in range(len(hist)):
if int(y) <= hist[i]:
splot += printcolour(pch, True, colour, return_str)
else:
splot += printcolour(" ", True, colour, return_str)
splot += print_return_str('', return_str=return_str)
xs = hist.keys()

splot += print_return_str(" " * (nlen + 1) + "-" * len(xs),
return_str=return_str)

if xlab:
xlen = len(str(float((max_y) / height) + max_y))
for i in range(0, xlen):
splot += printcolour(" " * (nlen + 1), True, colour, return_str)
for x in range(0, len(hist)):
num = str(bins[x])
if x % 2 != 0:
pass
elif i < len(num):
splot += print_return_str(num[i], end=' ',
return_str=return_str)
else:
splot += print_return_str(" ", end=' ',
return_str=return_str)
splot += print_return_str('', return_str=return_str)

center = max(map(len, map(str, [n, min_val, mean, max_val])))
center += 15

if showSummary:
splot += print_return_str('', return_str=return_str)
splot += print_return_str("-" * (2 + center), return_str=return_str)
splot += print_return_str("|" + "Summary".center(center) + "|",
return_str=return_str)
splot += print_return_str("-" * (2 + center), return_str=return_str)
summary = "|" + ("observations: %d" % n).center(center) + "|\n"
summary += "|" + ("min value: %f" % min_val).center(center) + "|\n"
summary += "|" + ("mean : %f" % mean).center(center) + "|\n"
summary += "|" + ("sd : %f" % sd).center(center) + "|\n"
summary += "|" + ("max value: %f" % max_val).center(center) + "|\n"
summary += "-" * (2 + center)
splot += print_return_str(summary, return_str=return_str)

if return_str:
return splot