I am trying to show cause and effect by displaying lines that are connected by two separate y axes.
eps_surprise = [56.15, 80.41, 218.48, 5.67, 2.99, 5.67]
stock_movement = [-5.72, 14.52, 18.78, -6.77, 6.03, -6.77]
fig, ax = plt.subplots()
y = list(zip(eps_surprise,stock_movement))
for i in y:
ax.plot((0,1),i)
plt.show()
As you can see in the above chart, I want to include a second y axis that would have a range limited to the min
and max
of stock_movement
. However, my attempts in doing so do not result in the desired chart, as what is plotted is then based on the second axis alone, and not the first.
import matplotlib.pyplot as plt
eps_surprise = [56.15, 80.41, 218.48, 5.67, 2.99, 5.67]
stock_movement = [-5.72, 14.52, 18.78, -6.77, 6.03, -6.77]
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.set_ylim(min(eps_surprise),max(eps_surprise))
ax2.set_ylim(min(stock_movement),max(stock_movement))
y = list(zip(eps_surprise,stock_movement))
for i in y:
plt.plot((0,1),i)
plt.show()
The desired output would look something like as follows:
CodePudding user response:
Not sure if this is what you are asking exactly, but given your question it's the best I can picture.
import matplotlib.pyplot as plt
eps_surprise = [56.15, 80.41, 218.48, 5.67, 2.99, 5.67]
stock_movement = [-5.72, 14.52, 18.78, -6.77, 6.03, -6.77]
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.set_ylim(min(eps_surprise),max(eps_surprise))
ax2.set_ylim(min(stock_movement),max(stock_movement))
# plot eps surprise and stock movement on the two separate axes
l1 = ax1.plot(eps_surprise, 'k--', label = 'eps surprise')
l2 = ax2.plot(stock_movement, 'r', label = 'stock movement')
# create legend for both axes
lns = [l1[0], l2[0]]
labs = [l.get_label() for l in lns]
ax2.legend(lns, labs)
ax1.set_ylabel('eps surprise')
ax2.set_ylabel('stock movement')
Honestly, though, if I were trying to show a relationship between two variables, I'd be more tempted to make a scatter plot or a regression.
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit([[i,] for i in eps_surprise],
[[i,] for i in stock_movement])
x = [[min(eps_surprise)], [max(eps_surprise)]]
plt.plot(eps_surprise, stock_movement, '.')
plt.plot(x, regressor.predict(x))
plt.grid()
plt.xlabel('eps surprise')
plt.ylabel('stock movement')
UPDATE
Based on the update in your question of how you want your original figure to look, here's how I would do it. The second set of axes are purely for labelling and instead I scaled the stock movement values to fit on your ax1
scale.
import matplotlib.pyplot as plt
def map_to_eps(stock_movement, eps_surprise):
ybounds = [min(stock_movement), max(stock_movement)]
dy = ybounds[1] - ybounds[0]
xbounds = [min(eps_surprise), max(eps_surprise)]
dx = xbounds[1] - xbounds[0]
return([(y - ybounds[0]) / dy * dx xbounds[0] for y in stock_movement], dy, dx)
eps_surprise = [56.15, 80.41, 218.48, 5.67, 2.99, 5.67]
stock_movement = [-5.72, 14.52, 18.78, -6.77, 6.03, -6.77]
(stock_eps, dstock, deps) = map_to_eps(stock_movement, eps_surprise)
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.set_ylim(min(eps_surprise) - 0.05 * deps,max(eps_surprise) 0.05 * deps)
ax2.set_ylim(min(stock_movement) - 0.05 * dstock ,max(stock_movement) 0.05 * dstock)
y = list(zip(eps_surprise,stock_eps))
for i in y:
ax1.plot((0,1),i)
plt.xticks([])
ax1.set_ylabel('eps surprise')
ax2.set_ylabel('stock movement')