1

Variations on this question have been asked multiple times before, but I have been unsuccessful in getting them to work. I may be (and most likely am) just inept at statistics.

I wish to plot a normal curve on top of this histogram using the data contained in the CSV file.

Many answers I have seen create a normal/gauss function, but I have excluded this from the MWE in case there is another, simpler way to do it.

Any assistance would be appreciated!

The histogram seeking a normal curve.

MWE:

\begin{filecontents*}{data.csv}
A
2
3
4
2
3
4
5
6
9
9
1
\end{filecontents*}

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{filecontents}
\usepackage{pgfplotstable}

\begin{document}

\begin{tikzpicture}
  \centering
\begin{axis}[
ybar interval,
/pgf/number format/.cd,
use comma,
1000 sep={},
title={Title},
xlabel={X Label},
ylabel={Y Label},
x label style={at={(axis description cs:0.5,-0.1)},anchor=north},
y label style={at={(axis description cs:0.05,0.5)},anchor=south},
xticklabel style={rotate=90, anchor=near xticklabel},
ytick distance=2,
width=\textwidth, %10.5cm
height=6cm,
ymin=0
]

%%%
\addplot +[
black,
fill=lightgray,
hist={bins=5,
data min=0,
data max=10,
}
] table[y=A, col sep=comma] {data.csv};

\end{axis}
\end{tikzpicture}
\end{document}
1
  • 1
    When you are saying "create a normal/gauss function" do you mean literally a Gaussian whose center, width and normalization you will provide, or are you seeing a way to extract the center and the width from the data and to draw the Gaussian then?
    – user121799
    Jan 22, 2019 at 0:12

1 Answer 1

2

Here is a proposal building on this answer.

\documentclass{standalone}
\usepackage{pgfplots}
\usepackage{filecontents}
\begin{filecontents*}{data.csv}
A
2
3
4
2
3
4
5
6
9
9
1
\end{filecontents*}

\usepackage{pgfplotstable}

\newcommand\GetMean[2]{% from https://tex.stackexchange.com/a/268942/121799
  \pgfplotstableread{#1}\tableA
  \pgfplotstableset{
    create on use/new/.style={
    create col/expr={\pgfmathaccuma + \thisrow{#2}}},
  }
  \pgfplotstablegetrowsof{\tableA}
  \pgfmathsetmacro{\NumRows}{\pgfplotsretval}
  \pgfplotstablegetelem{\numexpr\NumRows-1\relax}{new}\of{#1} 
  \pgfmathsetmacro{\Sum}{\pgfplotsretval}
  \pgfmathsetmacro{\Mean}{\Sum/\NumRows}
}
\newcommand\GetVariance[3]{
  \pgfplotstableread{#1}\tableA
  \pgfplotstableset{
    create on use/new/.style={
    create col/expr={\pgfmathaccuma + (\thisrow{#2}-#3)^2}},
  }
  \pgfplotstablegetrowsof{\tableA}
  \pgfmathsetmacro{\NumRows}{\pgfplotsretval}
  \pgfplotstablegetelem{\numexpr\NumRows-1\relax}{new}\of{#1} 
  \pgfmathsetmacro{\SumSquares}{\pgfplotsretval}
  \pgfmathsetmacro{\Variance}{sqrt(\SumSquares)/\NumRows}
}


\begin{document}



\begin{tikzpicture}[declare function={%
gauss(\x,\y,\z)=1/(2*\z*sqrt(pi))*exp(-(\x-\y)^2/(2*\z^2));}]
\begin{axis}[
/pgf/number format/.cd,
use comma,
1000 sep={},
title={Title},
xlabel={X Label},
ylabel={Y Label},
x label style={at={(axis description cs:0.5,-0.1)},anchor=north},
y label style={at={(axis description cs:0.05,0.5)},anchor=south},
xticklabel style={rotate=90, anchor=near xticklabel},
ytick distance=2,
width=\textwidth, %10.5cm
height=6cm,
ymin=0
]

%%%
\addplot +[ybar interval,
black,
fill=lightgray,
hist={bins=5,
data min=0,
data max=10,
}
] table[y=A, col sep=comma] {data.csv};
\GetMean{data.csv}{A}

\GetVariance{data.csv}{A}{\Mean}

\addplot[no marks,domain=0:8,smooth,samples=51,thick,color=blue]{\Sum*gauss(x,\Mean,\Variance)};
\end{axis}
\end{tikzpicture}
\end{document}

enter image description here

1
  • Thanks @marmot, this indeed does the trick. It has also made me realise I wasn't clear in my original question (largely because I don't know what I'm talking about). I'll post another question.
    – Craig
    Jan 22, 2019 at 7:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.