Plotting with TikZ, Part III: Plotting a function defined by a formula, and plotting functions that go through certain points
In the last post, I described how I use TikZ to create a graph that might otherwise be created freehand:
In this post, I will describe one method for using TikZ to to plot a function defined by a formula, such as $$y = \left(2x^2  x  1\right)e^{x}.$$ Then I will show two ways to make a function go through a certain point.
Plotting from a formula
Simple example
There are a number of ways to achieve this, and PGF actually includes the functionality to perform calculations in TeX. (For example, I have used the PGF pseudorandom number generator in graphics. Someone even made TikZ code to generate a random city skyline.) However, for efficiency sake, I prefer to have the calculations done outside TeX, in a more efficient computer language.
The trick is to use the gnuplot
table import format. You simply have to generate a text file with a list of coordinates in the following form:
1.250000 11.779907
1.240000 11.456050
1.230000 11.138839
This file contains the coordinates $(1.25, 11.779907)$, $(1.24, 11.456050)$, $(1.23, 11.138839)$.
There are a number of ways to generate such a file. Since I like Python, I used the following (simple) Python script:


Now, this curve can be imported into your TikZ illustration using \draw
[…] plot
; in this case:
\draw[thick, blue, <>] plot[smooth] file {plot1.table};
Here is a complete example (with coordinate axes and everything):


And here is the output:
In my Python script above, I carefully chose the set of inputs $x$ (np.arange(1.25, 10.25, 0.01)
, i.e., every real number of the form $1.25 + 0.01k, \; k \in \mathbb{Z}$ in the interval $[1.25, 10.25)$) to keep $f(x) < 12$. This can also be handled computationally.
Example involving asymptotes
For example, suppose I want to plot $y = r(x)$, where $$r(x) = \frac{6x^3 + 21x^2  21x  36}{3x^3 + 3x^2  12x  12},$$ with $15.5 \leq x \leq 15.5$. Let’s additionally suppose I want to only see $y$values with $15.5 \leq y \leq 15.5$. (In other words, the “viewing rectangle” will be $[15.5, 15.5] \times [15.5, 15.5]$.)
Factoring the numerator and denominator, we have:
$$r(x) = \frac{6x^3 + 21x^2  21x  36}{3x^3 + 3x^2  12x  12} $$ $$\phantom{r(x)}= \frac{\left(x + 1\right) \left(2 x  3\right) \left(3 x + 12\right)}{\left(x + 1\right) \left(x + 2\right) \left(3 x  6\right)}$$ $$\phantom{r(x)}= \frac{\left(2 x  3\right) \left(3 x + 12\right)}{\left(x + 2\right) \left(3 x  6\right)}, \; x \not = 1.$$
As you can see, we will have vertical asymptotes at $x = 2$ and $x = 2$, and a hole at $x = 1$. There will also be a horizontal asymptote at $y = 2$.
To handle the asymptotes, we plot the function $$\hat r(x) = \frac{\left(2 x  3\right) \left(3 x + 12\right)}{\left(x + 2\right) \left(3 x  6\right)}$$ along three intervals:
 $[15.5, 2)$,
 $(2, 2)$, and
 $(2, 15.5]$
(Actually, for each of the above intervals $I$, we plot something approximating $\left\{(x, \hat r(x)): x \in I \text{ and } \hat r(x)\leq 16\right\}$.)
Here is the Python script:


Here is the corresponding LaTeX code:


And here is the result:
Plotting functions that go through certain points: two ways
Suppose I want to plot a function that go through certain points, say:
 $(4, 2)$,
 $(1, 6)$,
 $(2, 3)$, and
 $(4, 5)$.
I want the function to be differentiable.
Method one: Bézier curves
Recall from the last post that a (cubic) Bézier curve is specified by four points:
 A start point ($(x_0, y_0)$ in the diagram below)
 Two control points ($(x_1, y_1)$ and $(x_2, y_2)$ in the diagram below)
 An end point ($(x_3, y_3)$ in the diagram below)
The syntax is: \draw (
$x_0, y_0$) .. controls (
$x_1, y_1$) and (
$x_2, y_2$) .. (
$x_3, y_3$);
Now, we can combine multiple Bézier curves into a single \draw
. For example, \draw (
$x_0, y_0$) .. controls (
$x_1, y_1$) and (
$x_2, y_2$) .. (
$x_3, y_3$) .. controls (
$x_4, y_4$) and (
$x_5, y_5$) .. (
$x_6, y_6$);
will produce:
In general, this curve will not necessarily be differentiable. We can get differentiability by ensuring that $(x_2, y_2)$, $(x_3, y_3)$ and $(x_4, y_4)$ are colinear (i.e., the end of the first Bézier curve has the same derivative as the beginning of the second) with $x_2 \not = x_3$:
Keeping these principles in mind, we can plot a function going through the desired points with:


Here is the output:
Method two: Polynomial interpolation
SciPy’s interpolation functionality can find a smooth function that passes through an arbitrary list of points. Here is an example of a Python script to produce such a function and create a table in the necessary format:


Note that if we had set coords = [(4, 2), (1, 6), (2, 3), (4, 5)]
, then the resulting function would not have had a defined value outside of the interval $[4, 4]$.
To plot, we use the following tikzpicture
:


Here is the result:
As we have seen, creating plots with TikZ allows you a deep amount of control over the final result, and can be especially powerful when combined with a programming language such as Python.