在 Matplotlib 中跨两个 y 轴映射单独的线

Map individual lines across two y axes in Matplotlib

我试图通过显示由两个单独的 y 轴连接的线来显示因果关系。


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()

正如您在上面的图表中看到的,我想包括第二个 y 轴,其范围限制在 stock_movementminmax 范围内。然而,我这样做的尝试并没有产生所需的图表,因为绘制的内容仅基于第二个轴,而不是第一个轴。

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()

所需的输出如下所示:

不确定这是否正是您要问的问题,但考虑到您的问题,这是我能想象的最好的情况。

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')

不过,老实说,如果我试图显示两个变量之间的关系,我会更倾向于绘制散点图或回归。

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')

更新

根据您对原始图形的外观问题的更新,我会这样做。第二组轴纯粹用于标记,而是我缩放了股票变动值以适合您的 ax1 比例。

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')