Vectors are extremely important in linear algebra and beyond. One of the most common visual representations of a vector is the arrow. Here we will learn how to plot vectors with Matplotlib. The title image shows two vectors and their sum. As a first step we will plot the vectors originating at 0, shown below.
import matplotlib.pyplot as plt import numpy as np vectors = np.array(([2, 0], [3, 2])) vector_addition = vectors + vectors vectors = np.append(vectors, vector_addition[None,:], axis=0) tail = [0, 0] fig, ax = plt.subplots(1) ax.quiver(*tail, vectors[:, 0], vectors[:, 1], scale=1, scale_units='xy', angles = 'xy', color=['g', 'r', 'k']) ax.set_xlim((-1, vectors[:,0].max()+1)) ax.set_ylim((-1, vectors[:,1].max()+1))
We have two vectors stored in our
vectors array. Those are
[2, 0] and
[3, 2]. Both in order of [x, y] as you can see from the image. We can perform vector addition between the two by simply adding
vectors + vectors. Then we use
np.append so we have all three vectors in the same array. Now we define the origin in
tail, because we will want the tail of the arrow to be located at
[0, 0]. Then we create the figure and axes to plot in with
plt.subplots(). The plotting itself can be done with one call to the
ax.quiver method. But it is quite the call, with a lot of parameters so let’s go through it.
First, we need to define the origin, so we pass
*tail. Why the asterisk?
ax.quiver really takes two parameters for the origin, X and Y. The asterisk causes [0, 0] to be unpacked into those two parameters. Next, we pass the x coordinates (
vectors[:, 0]) and then the y coordinates (
vectors[:, 1]) of our vectors. The next three parameters
angles are necessary to make the arrow length match the actual numbers. By default, the arrows are scaled, based on the average of all plotted vectors. We get rid of that kind of scaling. Try removing some of those to get a better idea of what I mean. Finally, we pass three colors, one for each arrow.
So what do we need to plot the head to tail aligned vectors as in the title image? We just need to pass the vectors where the origin is the other vector.
ax.quiver(vectors[1::-1,0], vectors[1::-1,1], vectors[:2,0], vectors[:2,1], scale=1, scale_units='xy', angles = 'xy', color=['g', 'r'])
This is simple because it is the same quiver method but it is complicated because of the indexing syntax. Now, we no longer unpack
*tail. Instead we pass x and y origins separately. In
vectors[1::-1,0] the 0 gets the x coordinates. -1 inverts the array. If we would not invert, each vector would be it’s own origin. The 1 skips the first vector, which is the summed vector because we inverted.
vectors[1::-1,1] gives us the y coordiantes. Finally we just need to skip the summed vector when we pass x and y magnitudes. The rest is the same.
So that’s it. Unfortunately,
ax.quiver only works for 2D vectors. It also isn’t specifically made to present vectors that have a common origin. Its main use case is to plot vector fields. This is why some of the plotting here feels clunky. There is also
ax.arrow which is more straightforward but only creates one arrow per method call. I hope this post was helpful for you. Let me know if you have other ways to plot vectors.
3 thoughts on “Plotting 2D Vectors with Matplotlib”
Your program does not work.
Produces the following error:
—> 12 ax.quiver(*tail,
13 vectors[:, 0],
14 vectors[:, 1],
ValueError: Argument U has a size 3 which does not match 1, the number of arrow positions
The issue you describe does not occur on my end. Maybe a version problem? Particularly the Matplotlib version? My environment: matplotlib 3.1.3; numpy 1.20.2; Python 3.7.6.
With Python 3.8.5, MatPlotLib 3.3.4 and NumPy 1.19.2, replace
tail = [0, 0]
tail = [[0, 0, 0], [0, 0, 0]]
By the way, thanks Daniel for this nice example, clearer than all I could find elsewhere until now 😉