Ova

How to Draw an Arrow in Python?

Published in Matplotlib Plotting 5 mins read

Drawing arrows in Python is most effectively achieved using the matplotlib library, a powerful tool for creating static, animated, and interactive visualizations. The primary function for drawing arrows directly is matplotlib.pyplot.arrow().

Using matplotlib.pyplot.arrow()

The matplotlib.pyplot.arrow() function allows you to draw an arrow by specifying its base coordinates and its length along the x and y directions. This method is ideal when you know the starting point and the vector components of your arrow.

Function Syntax

The core syntax for drawing an arrow is:

matplotlib.pyplot.arrow(x, y, dx, dy, **kwargs)

Key Parameters

Understanding the fundamental parameters is crucial for drawing accurate arrows:

  • x: The x-coordinate of the arrow's starting point (its base).
  • y: The y-coordinate of the arrow's starting point (its base).
  • dx: The length of the arrow along the x-direction. This determines how far the arrow extends horizontally from x.
  • dy: The length of the arrow along the y-direction. This determines how far the arrow extends vertically from y.
  • `kwargs`**: Optional keyword arguments for extensive customization of the arrow's appearance, such as color, width, head size, and more.

Basic Example

Let's draw a simple arrow starting at (0, 0) and extending to (1, 1):

import matplotlib.pyplot as plt

# Create a figure and an axes
fig, ax = plt.subplots()

# Draw an arrow from (0,0) with dx=1 and dy=1
ax.arrow(0, 0, 1, 1, head_width=0.05, head_length=0.1, fc='blue', ec='blue')

# Set plot limits for better visibility
ax.set_xlim(-0.5, 1.5)
ax.set_ylim(-0.5, 1.5)

# Add labels and title
ax.set_title("Simple Matplotlib Arrow")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.grid(True)

plt.show()

Customizing Your Arrows

The **kwargs parameter provides a wealth of options to control every aspect of your arrow's look. Here are some commonly used customization options:

Parameter Description Example Value
color or c Color of the arrow. 'red', '#FF0000'
fc Face color of the arrow head. 'green'
ec Edge color of the arrow body and head. 'black'
width Width of the arrow's body. 0.01
head_width Width of the arrow's head. 0.05
head_length Length of the arrow's head. 0.1
length_includes_head If True, the dx and dy values include the head's length. Defaults to False. True, False
shape Shape of the arrow head ('full', 'left', 'right'). 'full'
overhang Fraction of the head that overhangs the arrow body. 0.2

Example with Customization

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(7, 5))

# Arrow 1: Basic, pointing right
ax.arrow(0, 0, 1, 0, head_width=0.08, head_length=0.15, fc='red', ec='red', label="Red Arrow")

# Arrow 2: Thicker, green, pointing up-left
ax.arrow(0.5, 0.5, -0.4, 0.4, width=0.02, head_width=0.1, head_length=0.1, fc='green', ec='green', label="Green Arrow")

# Arrow 3: Thin, blue, long head
ax.arrow(0.2, 0.8, 0.6, -0.6, width=0.005, head_width=0.06, head_length=0.2, fc='blue', ec='blue', label="Blue Arrow")

ax.set_xlim(-0.1, 1.1)
ax.set_ylim(-0.1, 1.1)
ax.set_title("Customized Arrows in Matplotlib")
ax.set_xlabel("X-coordinate")
ax.set_ylabel("Y-coordinate")
ax.legend()
ax.grid(True, linestyle='--', alpha=0.7)

plt.show()

Drawing Arrows Between Two Specific Points

Often, you'll have two points, (x1, y1) and (x2, y2), and you want to draw an arrow from the first to the second. In this scenario, you need to calculate dx and dy:

  • dx = x2 - x1
  • dy = y2 - y1
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

point1 = (0.2, 0.3)
point2 = (0.8, 0.7)

# Calculate dx and dy
dx_val = point2[0] - point1[0]
dy_val = point2[1] - point1[1]

# Draw the arrow
ax.arrow(point1[0], point1[1], dx_val, dy_val,
         head_width=0.04, head_length=0.08, fc='purple', ec='purple',
         length_includes_head=True) # Ensure arrow points exactly to point2

# Mark the points
ax.plot(point1[0], point1[1], 'o', color='black', label="Start Point")
ax.plot(point2[0], point2[1], 'x', color='black', label="End Point")

ax.set_xlim(0, 1)
ax.set_ylim(0, 1)
ax.set_title("Arrow Between Two Points")
ax.legend()
ax.grid(True)

plt.show()

Tip: Setting length_includes_head=True in plt.arrow can be very useful when you want the tip of the arrow to precisely land on (x + dx, y + dy). Otherwise, the head's length will extend beyond this point.

Alternative: Using plt.annotate() for Arrows with Text

For situations where you need an arrow pointing to a specific data point and associated text, matplotlib.pyplot.annotate() is a more versatile function. It's particularly useful for annotations on plots.

import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots()

x = np.linspace(0, 10, 100)
y = np.sin(x)

ax.plot(x, y, label='sin(x)')

# Annotate a specific point with an arrow
peak_x = x[np.argmax(y)] # Find x-coordinate of the peak
peak_y = np.max(y)      # Find y-coordinate of the peak

ax.annotate('Peak Value', xy=(peak_x, peak_y), xytext=(peak_x + 2, peak_y + 0.5),
            arrowprops=dict(facecolor='orange', shrink=0.05, width=2, headwidth=8),
            horizontalalignment='left', verticalalignment='bottom')

ax.set_title("Annotating a Plot with an Arrow")
ax.set_xlabel("X-axis")
ax.set_ylabel("Y-axis")
ax.legend()
ax.grid(True)

plt.show()

In plt.annotate():

  • xy: The (x, y) coordinates of the point being annotated (where the arrow points to).
  • xytext: The (x, y) coordinates where the text is placed.
  • arrowprops: A dictionary of properties for the arrow, similar to **kwargs for plt.arrow but with slightly different parameter names (e.g., facecolor, shrink, width, headwidth, headlength).

For more details on matplotlib's capabilities, including advanced arrow customizations and other plotting options, refer to the official Matplotlib Documentation.