Reputation: 1536
I have the following plot, showing a linear relationship (black) and its residuals (blue). The red dotted lines show the upper and lower bounds for the residuals, and the vertical red line shows the range:
Here's how I've coded the bounds for the residuals:
plt.hlines(y = max(model.resid), xmin = min(x), xmax = max(x),
color = 'r', linestyle = 'dotted')
plt.hlines(y = min(model.resid), xmin = min(x), xmax = max(x),
color = 'r', linestyle = 'dotted')
plt.vlines(label = 'Range of residuals: %g'%(max(model.resid) - min(model.resid)),
x = min(x), ymin = min(model.resid), ymax = max(model.resid),
color = 'r', linestyle = 'solid')
I want the vertical line to be a double-headed arrow, so I tried using arrowprops = {'arrowstyle': '<->'}
after the linestyle
, but I got AttributeError: Unknown property arrowprops
.
All of the questions and example I've found show how to make an arbitrarily-positioned arrow, but none of them give a nicely-proportioned head.
Is there an easy way to convert the line to a double-headed arrow?
Upvotes: 2
Views: 5042
Reputation: 39052
Here is a minimal working solution to your problem. The main keyword here is arrowstyle="<->"
. I personally prefer to use plt.text
separately to put the text independently of the arrow end point in the plot. It gives you more freedom. I had to generate random data due to absence of your data but I kept the x
and y
range similar to yours. You can adapt your code accordingly. Your problem was that you were assigning arrowprops
which is a property of annotate
to vlines
.
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure(figsize=(8, 5))
ax = fig.add_subplot(111)
x = np.linspace(-0.4, 0.6, 1000)
y = np.random.normal(0, 0.033, 1000)
plt.plot(x, y, 'o')
plt.hlines(y = max(y), xmin = min(x), xmax = max(x),
color = 'r', linestyle = 'dotted')
plt.hlines(y = min(y), xmin = min(x), xmax = max(x),
color = 'r', linestyle = 'dotted')
ax.annotate("",
xy=(min(x), min(y)), xycoords='data',
xytext=(min(x), max(y)), textcoords='data',
arrowprops=dict(arrowstyle="<->",
connectionstyle="arc3", color='r', lw=2),
)
plt.text(1.2*min(x), max(y), 'Range of residuals: %g'%(max(y) - min(y)),
rotation = 90, fontsize = 16)
plt.xlim(1.3*min(x), 1.3*max(x))
Output
Upvotes: 2