# Smooth curve through points with pgfplots

I know that one can get smooth point connections with option smooth to \addplot that takes the previous and the next point into account, but this still connects all the points.

How can I draw a smooth curve through the points using pgfplots that are not necessarily connected? I'm not fully sure if this is correct, but I think I'm looking for "bezier curves" (correct me if wrong). To be clear: I do not want curve-fitting like one can do with gnuplot, just some "sloppy-smooth" connecting of points.

Example picture (not from my data!):

Here is my real data, they don't follow a known, analytical, mathematical function:

43  3.22
44  3.26
45  3.28
46  3.40
47  3.60
48  3.53
49  3.50
50  3.60
51  3.59
52  3.54
53  3.55
54  3.51
55  3.35
56  3.45
57  3.42
58  3.43
59  3.42
60  3.42
61  3.43
62  3.47
63  3.45
64  3.40
65  3.20
66  3.21
67  3.17
68  3.20
69  3.22
70  3.36
71  3.37
72  3.37
73  3.30
74  3.33
75  3.39
76  3.41
77  3.34
78  3.45
79  3.42
80  3.38
81  3.33
82  3.15
83  3.35
84  3.33
85  3.20
86  3.24
87  3.20

-
You are asking for the hobby package that Andrew Stacey created for TikZ. –  percusse Apr 18 '13 at 17:35
@percusse: I agree, although hobby curves do go through all the specified points –  Jake Apr 18 '13 at 17:36
@Jake oops, nice catch! It might still smoothen out though. –  percusse Apr 18 '13 at 17:41
@FooBar: Could you edit your question to include an example of the data you want to smooth? –  Jake Apr 18 '13 at 17:44
@Jake done. It does not follow any known mathematical function, however. Just some "random" points. –  Foo Bar Apr 18 '13 at 17:49

Using the gnuplot backend, put your points in a file.dat, and compile twice with -shell-escape

\documentclass{article}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}
\addplot +[no markers, raw gnuplot] gnuplot {
plot 'file.dat' smooth sbezier;
};
\addplot +[only marks, raw gnuplot] gnuplot {
plot 'file.dat' with points;
};
\end{axis}
\end{tikzpicture}
\end{document}

-
Thanks to everyone, but I like this solution most, since I'm using gnuplot already. But I upvoted all solutions, since they are all very good. –  Foo Bar Apr 18 '13 at 18:56

One thing you could do is to calculate a LOESS smooth of the data. I don't know of a way to do this in LaTeX directly, but you could preprocess your data in R (which is free and useful to know, at any rate).

The following code reads the data from a file called data.dat and smoothes it using a span of 0.3 (i.e. it takes 30% of the data around each point into account for calculating a polynomial), and then writes it to a file called smooth.dat:

datapoints = read.delim('data.dat', header=F)
smooth=loess(datapoints$V2 ~ datapoints$V1, span=0.3)
write.table(data.frame(smooth$x,smooth$fitted), 'smooth.dat',sep='\t', quote=F, col.names=F, row.names=F)


Which you can then plot using:

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

\begin{document}

\begin{tikzpicture}
\begin{axis}
\end{axis}

\end{tikzpicture}
\end{document}

-

here is your data with a Bezier curve:

\documentclass{article}% run with xelatex
%\usepackage[pdf]{pstricks}% for pdflatex --shell-escape
\usepackage{pst-plot}
\begin{document}
\psset{xunit=0.2,yunit=5}
\begin{pspicture}(0,0)(50,1)
\pstScalePoints(1,1){40 sub}{3 sub}
\psaxes[ticksize=0 5pt,Dy=0.2,Dx=10,Ox=40,Oy=3]{->}(0,0)(50,1)