# How to compute an histogram (plot bars) binning the values from a .csv using TeX?

I've a .csv with a column of acquired measures. I would like to make the histogram bins using TeX from the measures distribution so I have to create the bins first. I haven't found any reference to perform an automatic binning or to set manually the intervals to produce the bins. I would like to know how can I do that and if I can perform non-uniform bins histogram.

\documentclass[border=5mm]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots, pgfplotstable}

\begin{filecontents}{data.csv}
dist
1
2
2.5
2
1
3.5
3
1
3
2
1
1
0.5
1
1.5
1
\end{filecontents}

\begin{document}
\begin{tikzpicture} \begin{axis}
\addplot[xbar] table [
col sep=comma,
x=dist
] {data.csv};
\end{axis}
\end{tikzpicture}
\begin{tikzpicture}
\begin{axis}
\addplot [ybar interval] table [
col sep=comma,
y=dist
] {data.csv};
\end{axis}
\end{tikzpicture}
\end{document}


I perform this usually in python (code below) this should be the output:

import matplotlib.pyplot as plt
dist=[1, 2, 2.5, 2, 1, 3.5, 3, 1, 3, 2, 1, 1, 0.5, 1, 1.5, 1]
plt.hist(dist,7) #Compute the histogram of a set of data.


## 4 Answers

You can use the PGFPlots statistics library for this:

\documentclass[border=5mm]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots, pgfplotstable}
\usepgfplotslibrary{statistics}

\begin{filecontents}{data.csv}
dist
1
2
2.5
2
1
3.5
3
1
3
2
1
1
0.5
1
1.5
1
\end{filecontents}

\begin{document}
\begin{tikzpicture}
\begin{axis}[
ybar,
ymin=0
]
\addplot +[
hist={
bins=7,
data min=0.5,
data max=4
}
] table [y index=0] {data.csv};
\end{axis}
\end{tikzpicture}
\end{document}

• Can I put the data in an external file data.csv? Your example works for me, but the histogram is blank, when I try to implement it. Feb 24, 2015 at 12:31
• @tommy.carstensen: Yes, you can use an external file. Actually, that's the real way you would do it, the filecontents approach used in my answer is just to make copying and pasting the example easier.
– Jake
Feb 24, 2015 at 12:34
• Excellent! Thanks! I got a "No room for new \write" error message otherwise. Feb 24, 2015 at 12:37

Here, have some gnuplot. Using the gnuplottex package, typeset using pdflatex --shell-escape:

# Code

\documentclass{standalone}
\usepackage{gnuplottex}
\usepackage{filecontents}
\begin{filecontents}{data.csv}
1
2
2.5
2
1
3.5
3
1
3
2
1
1
0.5
1
1.5
1
\end{filecontents}
\begin{document}
\begin{gnuplot}[terminal=cairolatex,terminaloptions={pdf color}]
set xrange [0:4]
set yrange [0:8]
set style fill solid 1
plot 'data.csv' using 1:(1) smooth frequency with boxes title 'Data'
\end{gnuplot}
\end{document}


# Output

• I finally got gnuplot inside tex working, based on your sample. Thanks! Jun 3, 2014 at 15:29

Here is a solution using pst-plot:

\documentclass{article}

\usepackage{pst-plot}

\savedata{\data}[{{0.5,1},{1,7},{1.5,1},{2,3},{2.5,1},{3,2},{3.5,1}}]

\begin{document}

\psset{xunit = 2}
\begin{pspicture}(-0.23,-0.53)(4,7.5)
\listplot[
plotstyle = bar,
barwidth = 0.8,
linecolor = red,
fillstyle = solid,
fillcolor = blue!70
]{\data}
\psaxes[
Dx = 0.5,
xticksize = -4pt 0
]{->}(4,7.5)
\end{pspicture}

\end{document}


P.S. I can't figure out exactly what the data are, but from your plot I've guessed. If I'm wrong, you should be able to change it yourself.

• I'm sorry I've saw only now that although the plotted data result is right the way in which is achieve is not what I was asking. The goal of my question is to perform the binning with TeX (See the Jake answer or the analogous Python code) not to plot an histogram with pre-computed bins. Thanks however for the help!
– G M
Jan 13, 2014 at 18:49
• Beware, however, that this is not a histogram, but a bar plot. Nov 27, 2018 at 7:48

Although is not a pure LaTeX approarch, may be an alternative to someone could be a Sweave (.Rnw) file, that R can convert in a true .tex file.

With a well configured LaTeX editor as TeXworks, or RStudio this is not extra work for the user, as you simply edit the .Rnw file an the PDF file is compiled with one click, without dealing with R nor intermediate LaTeX files.

With this approach is easy make non-uniform bins histograms (with option breaks in the R plot) and set the x-axis range (option xlim):

\documentclass{article}
\begin{document}
\SweaveOpts{concordance=TRUE}

Automatic breaks with range fixed:

<<examplea,echo=F,fig=T,height=3>>=
sample <- read.table("data.csv", header=TRUE, sep="", na.strings="NA", dec=".", strip.white=TRUE)
hist(sample$X1, xlim=c(0,4), main="",xlab="", ylab="", col="orange") @ Manual uneven breaks: <<exampleb,echo=F,fig=T,height=3>>= hist(sample$X1, breaks=c(0.5,1,1.5,3.5),freq=T, main="",xlab="", ylab="", col="cyan")
@

Automatic fixed breaks at these values:

<<examplec,echo=F,fig=T,height=3>>=
mybreaks <- as.vector(exp(seq(log(.01),log(6),by=0.5)))
mybreaks
hist(sample\$X1, breaks=mybreaks, freq=T,main="",xlab="", ylab="", col="red")
@

\end{document}

• +1 thanks! I think maybe this is better regarding performance! the performance of the pure tex version are not so good (is quite slow) and so if someone have big data file he should use this alternative!
– G M
Jan 15, 2014 at 11:09