Skip to content

Instantly share code, notes, and snippets.

@chbrown
Created October 27, 2013 04:15
Show Gist options
  • Save chbrown/7177912 to your computer and use it in GitHub Desktop.
Save chbrown/7177912 to your computer and use it in GitHub Desktop.
Numpy-powered CLI histogram
import os
import numpy as np
term_rows, term_columns = map(int, os.popen('stty size', 'r').read().split())
def hist(xs, margin=10, width=term_columns):
# I'm not sure why my font in iterm doesn't like \u2588, but it looks weird.
# It's too short and not the right width.
chars = u' \u2581\u2582\u2583\u2584\u2585\u2586\u2587\u2589'
width = term_columns - (2 * (margin + 1))
# compute the histogram values as floats, which is easier, even though we renormalize anyway
hist_values, bin_edges = np.histogram(xs, bins=width, density=True)
# we want the highest hist_height to be 1.0
hist_heights = hist_values / max(hist_values)
# np.array(...).astype(int) will floor each value
hist_chars = (hist_heights * (len(chars) - 1)).astype(int)
cells = [chars[hist_char] for hist_char in hist_chars]
# margin - size_of_integral_part - 1 (for +/- sign) - 1 (for decimal point) - 1 (because int floors, not ceils)
float_fmt = lambda x: '%.*f' % (margin - int(np.log10(abs(x))) - 3, x)
print '%*s[%s]%-*s' % (margin, float_fmt(bin_edges[0]), u''.join(cells), margin, float_fmt(bin_edges[-1]))
# example:
import scipy.stats
draws = scipy.stats.norm.rvs(size=1000, loc=240, scale=50)
hist(draws)
@chbrown
Copy link
Author

chbrown commented Oct 27, 2013

u'\u2588' looks out of whack in both Monaco and Droid Sans Mono, but it might be desirable in other terminals, so toying with the chars constant would be wise.

@chbrown
Copy link
Author

chbrown commented Oct 27, 2013

Example result:

$ py terminal.py
 86.746629[          ▁▁▂▂▁▃▃▃▂▄▅▅▅▅▉▅▇▆▄▅▇▄▃▅▃▃▂▂▁▂▁ ▁▁                      ]471.45819

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment