Постепенно добавлять и отображать новые данные в строке matplotlib

Вопрос

Как добавить данные к существующей строке matplotlib и отобразить только добавленную часть строки без перерисовки всей строки?

Комментарии

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

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

import matplotlib.pyplot as plt
import numpy as np
import time

# User input
N_chunk = 10000
N_iter = 100

# Prepare data
xx = list(range(N_chunk))
yy = np.random.rand(N_chunk).tolist()

# Prepare plot
fig, ax = plt.subplots()
ax.set_xlim([0,N_chunk])  # observe only the first chunk
line, = ax.plot(xx,yy,'-o')
fig.show()

# Appending data and redraw
dts = []
for i in range(N_iter):
    t0 = time.time()
    xs = xx[-1]+1
    xx.extend(list(range(xs,xs+N_chunk)))
    yy.extend(np.random.rand(N_chunk).tolist())
    line.set_data(xx,yy)
    fig.canvas.draw()
    dt = time.time() - t0
    dts.append(dt)
    plt.pause(1e-10)
plt.close()

# Plot the time spent for every redraw
plt.plot(list(range(N_iter)), dts, '-o')
plt.xlabel('Number of times a portion is added')
plt.ylabel('Redraw time [sec]')
plt.grid()
plt.show()

Время перерисовки в зависимости от размера данных


person pch    schedule 08.05.2020    source источник
comment
вы проверили этот stackoverflow.com/a/10944967/6660638   -  person Epsi95    schedule 08.05.2020
comment
Я проверил это, спасибо. Они предложили аналогичный вариант моего кода: строка перерисовывается целиком. Кстати, использование np.append для больших массивов увеличивает время каждой перерисовки до 10 раз.   -  person pch    schedule 08.05.2020


Ответы (1)


Вот модифицированная версия вашего кода, использующая интерактивный режим matplotlib.

import matplotlib.pyplot as plt
import numpy as np
import time

# User input
N_chunk = 10000
N_iter = 100

# Prepare data
xx = np.arange(N_chunk)
yy = np.random.rand(N_chunk)

# Prepare plot
fig, ax = plt.subplots()
#ax.set_xlim([0,N_chunk])  # observe only the first chunk
line = ax.plot(xx,yy,'-o')
plt.ion()   # set interactive mode
fig.show()

# Appending data
dts = []
for i in range(N_iter):
    t0 = time.time()
    xs = xx[-1]+1
    xx=np.arange(xs,xs+N_chunk)
    yy=np.random.rand(N_chunk)
    line=ax.plot(xx,yy,'-o')
    fig.canvas.draw()
    dt = time.time() - t0
    dts.append(dt)
    plt.pause(1e-10)
plt.close()

# Plot the time spent for every redraw
plt.plot(range(N_iter), dts, '-o')
plt.xlabel('Number of times a portion is added')
plt.ylabel('Redraw time [sec]')
plt.grid()
plt.show() 

При раскомментированном ax.set_xlim время перерисовки:

Время перерисовки

С другой стороны, с комментарием ax.set_xlim:

Время перерисовки

Ясно, что вызов fig.canvas.draw() перерисовывает все. В вашем случае, комментируя ax.set_xlim([0,N_chunk]), вы перерисовываете такие вещи, как границы осей, метки галочек и т. д. Вы хотите исследовать блиттинг, как описано в этом SO, чтобы избежать перерисовки объектов осей.

person Sameeresque    schedule 10.05.2020
comment
Во-первых, вы изменили код: вы добавили больше строк вместо расширения исходной строки. Во-вторых, вы, похоже, путаете прокомментированные и непрокомментированные случаи. Очевидно, что если вы показываете ограниченную часть данных, рендеринг занимает меньше времени. - person pch; 12.05.2020
comment
Спасибо за ссылку. Blitting хорошо помогает, когда у вас в сюжете много художников, а обновлять нужно лишь некоторых из них. В моем случае представлен только художник. Во всяком случае, я попытался блицировать с помощью вашего подхода (добавьте отдельную строку для каждой новой порции данных). Он отлично работает вместе с обновлением фона каждый раз в цикле (наконец, ~ 0,03 секунды на перерисовку). Хотя у вас есть несколько строк, которые не связаны между собой. - person pch; 13.05.2020
comment
Суть моего кода в том, что он избавляется от расширения данных. Он добавляет новые данные, а также представляет существующие данные. Ваш код, с другой стороны, расширяет данные и отображает все данные. - person Sameeresque; 13.05.2020