Как создать новый сюжет на рисунке прямо под первым после события клика? - PullRequest
0 голосов
/ 19 мая 2019

Учитывая матрицу (список списков)

A = [[1, 2, 3],
     [4, 6, 8],
     [9, 12, 15]]

и список x = [1, 2, 3].

Каждая строка j (0 <= j <= 2) из A состоит из y -значения, так что всего можно создать 3 прямые линии в комбинации с x.

Теперь я хочу построить эти прямые линии на одном графике с помощью специальной функции.Если пользователь нажимает на графику, обработчик события должен получить x -позицию и создать еще один график прямо под первым.Этот график должен быть одномерным и отображать только данные столбца в A, индекс которого определяется положением x .

Пример: щелчок по x = 1 должен построить [1 4 9], x = 2 должен построить [2 6 12] и т. Д.

Я уже пытался добавить подплот, используя figure1.add_subplot(211) для первых графиков и figure1.add_subplot(212) в обработчике событий, и он также не работал.

A = [[1 2 3], [4 5 6], [7 8 9]]
x = [1 2 3]
figure1 = plt.figure()
plt.plot(x, A[0])
plt.plot(x, A[1])
plt.plot(x, A[2])

def onclick(event):
    Y = [A[i][int(event.xdata)] for i in range(0, 3)]
    plt.plot(Y)

figure1.canvas.mpl_connect('button_press_event', onclick)

1 Ответ

1 голос
/ 20 мая 2019

У меня есть следующий скрипт, который выполняет то, что было задано в вопросе:

  1. функция обратного вызова сильно прокомментирована
  2. ключевой момент заключается в том, что пределы оси не являются автоматическиобновлено, вы можете использовать ax.relim(); ax.autoscale_view() (подтверждение, это исходит из этого ответа от asmus ) в обратном вызове или заранее установить подходящие пределы, как я и решил.

вот это скрипт:

import matplotlib.pyplot as plt
from matplotlib.lines import Line2D

def get_x(event):
    x = event.xdata
    # if you clic outside the graph, do nothing
    if x is None : return
    # from abscissa to column index
    i = int(round(x)-1)
    # update the line ordinates --- this is much faster than redrawing
    # the line, in this example it doesn't matter but possibly one
    # deals with larger data sets...
    line.set_ydata([row[i] for row in A])
    # we start with a clean subplot, if we haven't already placed a
    # line in it it's high time to do that
    if a2.lines == [] : a2.add_line(line)
    # eventually it's the moment of redrawing the whole figure
    fig.canvas.draw_idle()

# the data
A = [[1, 2, 3],
     [4, 5, 6],
     [7, 8, 9]]
x = [ 1, 2, 3]

# THE key issue is to set properly and in advance all the axes,
# hence the share{x,y}
f, (a1, a2) = plt.subplots(2, 1, sharex='col', sharey='col')
a1.grid(1), a2.grid(1)

# the first subplot, nitpick: adjust the y limits
a1.plot(x, list(zip(*A)))
a1.set_ylim(0, 10)

# prepare a line to be plotted in the second subplot
line = Line2D([1,2,3], [0,0,0], color='black')

# bind our callback and show the figure
f.canvas.mpl_connect('button_press_event', get_x)
plt.show()

the non-interactive figure

...