Как сгенерировать несколько графиков, щелкнув один график для получения дополнительной информации, используя интерактивные события python

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

Вопрос:

  • Как создать 3-й график, щелкнув вторую точку данных графика? Можно ли это сделать?
  • Как создать более простые синтетические данные на 3 слоя?

Код, который я до сих пор:

"""
compute the mean and stddev of 100 data sets and plot mean vs stddev.
When you click on one of the mu, sigma points, plot the raw data from
the dataset that generated the mean and stddev
"""
import numpy as np
import matplotlib.pyplot as plt

X = np.random.rand(100, 1000)
xs = np.mean(X, axis=1)
ys = np.std(X, axis=1)

fig = plt.figure()
ax = fig.add_subplot(211)
bx = fig.add_subplot(212)

# ax.set_title('click on point to plot time series')
# bx.set_title('click on point to plot time series')


line, = ax.plot(xs, ys, 'bs', picker=5)  # 5 points tolerance
line1, = bx.plot(xs, ys, 'bo', picker=5)  # 5 points tolerance

def onpick(event):

    if event.artist!=line: return True

    N = len(event.ind)
    if not N: return True


    figi = plt.figure()
    for subplotnum, dataind in enumerate(event.ind):

        ax = figi.add_subplot(N,1,subplotnum+1)
        ax.plot(X[dataind])
        ax.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        ax.set_ylim(-0.5, 1.5)

        bx = figi.add_subplot(N,1,subplotnum+1)
        bx.plot(X[dataind])
        bx.text(0.05, 0.9, 'mu=%1.3f\nsigma=%1.3f'%(xs[dataind], ys[dataind]),
                transform=ax.transAxes, va='top')
        bx.set_ylim(-0.5, 1.5)

    figi.show()
    return True

fig.canvas.mpl_connect('pick_event', onpick)

plt.show()

1-й сюжет

Щелкнув точки данных на первом графике, будет создан второй график.

2-й сюжет

Теперь ожидаются генерации третьего сюжета, щелкнувшего вторую точку данных графика.

Я исследовал это, но я не увенчался успехом:-(:-(

Если мой подход неверен, предложите другую альтернативу.

Ответы

Ответ 1

синтетические данные на 3 уровня

import matplotlib.pyplot as plt
import numpy as np
# data source
data_bucket = {}

# l1: randn
# l2: sum(l1)
# l3: sum(l2)


# generate some 3 layer synthetic data
N = 1000
l1_count = 50
l2_count = 50
l3_count = 2
x = np.arange(N)
for j in range(l3_count):
    l3 = []
    for k in range(l2_count):
        l2 = []
        for m in range(l1_count):
            l1 = data_bucket[(j, k, m)] = np.random.randn(N)
            l2.append(np.sum(l1))
        l2 = data_bucket[(j, k)] = np.asarray(l2)
        l3.append(np.sum(l2))
    data_bucket[(j, )] = np.asarary(l3)

Функция выбора

# only hase to close over the data
def picker(event):
    print(event.artist.get_gid())
    print(event.ind)
    # some function to generate next data key from gid + index
    k = event.artist.get_gid() + tuple(event.ind)
    try:
        next_data = data_bucket[k]
    except KeyError:
        print("no generations of data left")
        return
    # make the previous generation of plot
    fig, ax = plt.subplots()
    # can use the key here to dispatch to different plotting functions
    ax.plot(next_data, gid=k, picker=5, ls='-')
    fig.canvas.mpl_connect('pick_event', picker)

Начальный график

fig, ax = plt.subplots()

for k in range(l3_count):
    k = (k, )
    ax.plot(data_bucket[k], gid=k, picker=5, ls='', marker='o')
fig.canvas.mpl_connect('pick_event', picker)

Сложная часть этого управления отображением между данными в текущем значении и следующем слое данных. Все художники mpl имеют атрибут gid, который может быть использован для однозначной идентификации, поэтому здесь я использую этот индекс +, чтобы генерировать ключи в словаре, которые являются наборами целых чисел различной длины. Это было первое, что появилось в моей голове при попытке создания синтетических трехслойных данных. В принципе будет работать любая система ключей, которая использует gid выбранного художника + индекс в этой строке → следующий уровень данных.

Затем вы можете использовать одну и ту же функцию выбора для всех ваших фигур, и ей нужно только закрыть источник данных. Все это могло бы (должно быть?) Свернуто в один класс.