#python #python-3.x #numpy #matplotlib #multidimensional-array
Вопрос:
x = np.array[[[8, 7, 1, 0, 3],
[2, 8, 5, 5, 2],
[1, 1, 1, 1, 1]],
[[8, 4, 1, 0, 0],
[6, 8, 5, 5, 2],
[1, 1, 1, 1, 1]],
[[2, 4, 0, 2, 3],
[2, 5, 5, 3, 2],
[1, 1, 1, 1, 1]],
[[4, 7, 2, 8, 0],
[1, 3, 6, 5, 2],
[1, 1, 1, 1, 1]]]
У меня есть NumPy
массив, называемый x
, и я хочу построить его. Каждые 5 столбцов данных здесь представляют 1 секунду. Таким образом, мой массив составляет 5*4=20 секунд данных. Я хочу, чтобы этот массив, который я нарисую с plt.imshow
помощью команды, увеличивался, добавляя его рядом с ним каждую секунду. Другими словами, только
[8, 7, 1, 0, 3],
[2, 8, 5, 5, 2],
[1, 1, 1, 1, 1]]
будет разыграна в первую секунду, затем
[[8, 7, 1, 0, 3, 8, 4, 1, 0, 0],
[2, 8, 5, 5, 2, 6, 8, 5, 5, 2],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]]
будет нарисован во вторую секунду, и так далее до 4 секунд.
Но перед этим нам нужно видеть, как наш массив увеличивается каждую секунду. Вы можете добраться до изображения, которое я хочу получить ниже.
Но здесь есть очень важная проблема. Мой реальный массив намного больше. Поэтому, когда я хочу преобразовать 3D-массив , который у меня есть , в 2D np.concatenate
, np.append
или indexing
мой компьютер выходит из строя, потому что массив слишком большой. Есть ли какой-нибудь способ сделать это с matplotlib
библиотекой, не преобразуя ее в 2D? Я думаю, что это можно сделать с помощью цикла for, но проблема здесь в том, что в примерах, которые я видел в Интернете, они полностью обновляют изображение, а не добавляют его рядом с другим.
Ответ №1:
ОБНОВЛЕННЫЙ ОТВЕТ:
Следующий код занял менее 5 минут работы на моем ноутбуке с 8 ГБ оперативной памяти и массивом данных формы (475,5400,200).
d1,d2,d3 = 475,5400,200 # dimensions of the data
# Create some data
values = np.zeros((d1,d2,d3))
values[:] = 1 np.cos(np.arange(d2)/200)[:,None]
values[:] *= 1 np.sin(np.arange(d1*d3)/1000).reshape(d1,d3)[:,None,:]
# Produce plots
fig = plt.figure(figsize=(10,2))
plt.xlim((0,d1*d3))
yaxis = range(d2,-1,-1)
vmin = values.min()
vmax = values.max()
# plot a background of zeros
plt.pcolormesh([0,d1*d3],[d2,0],[[0]], vmin=vmin,vmax=vmax)
plt.savefig('test-000.png')
plt.clf() # clear figure
# plot the data
for i,v in enumerate(values):
print(i)
plt.xlim((0,d1*d3)); plt.xticks([], ""); plt.yticks([], "")
xaxis = range(i*d3,(i 1)*d3 1)
plt.pcolormesh(xaxis,yaxis,v, vmin=vmin,vmax=vmax)
plt.savefig('test-{:03d}.png'.format(i 1), transparent=True)
plt.clf() # clear figure
plt.close()
Приведенный выше код создает 476 кадров, которые необходимо наложить, чтобы сформировать анимированный gif. Для этого я использовал ImageMagick:
convert -delay 2 -layers 'optimize' -dispose none test-*.png test.gif
Это результирующая анимация:
Я надеюсь, что этот метод работает и на вашем компьютере тоже!
…
ОРИГИНАЛЬНЫЙ ОТВЕТ: (не работает для OP, так как у его компьютера заканчивается оперативная память)
Я не знаю, как это сделать imshow
, но вот как я это сделал с pcolormesh
:
d1,d2,d3 = x.shape # dimensions of x
vmin = x.min()
vmax = x.max()
fig = plt.figure(figsize=(10,2))
plt.xlim((0,d1*d3))
yaxis = range(d2,-1,-1)
# plot a background of zeros
xaxis = range(0,d1*d3 1)
plt.pcolormesh(xaxis,yaxis,np.zeros((d2,d1*d3)), vmin=vmin,vmax=vmax)
plt.savefig('test-0.png')
# plot your data 5 seconds at a time
for i,xi in enumerate(x):
xaxis = range(i*d3,(i 1)*d3 1)
plt.pcolormesh(xaxis,yaxis,xi, vmin=vmin,vmax=vmax)
plt.savefig('test-{}.png'.format(i 1))
plt.close()
Этот фрагмент кода сохраняет кадр каждые 5 секунд в формате png. Чтобы создать анимированный gif ниже, я использовал ImageMagick: convert -delay 50 test*.png test.gif
Я уверен, что есть более эффективные способы создания анимации вместо сохранения каждого кадра, а затем создания gif из кадров. Однако у меня нет большого опыта работы с matplotlib и анимированными сюжетами, так что, может быть, кто-то еще может порекомендовать лучший способ создания анимированного gif?
Комментарии:
1. Спасибо, я собираюсь попробовать это.
2. Извините, но это не сработало. Массив, с которым я на самом деле работаю, слишком велик, и, вероятно, поэтому он не работает. Я думаю, что этот метод потребляет много оперативной памяти.
3. @mehmet_kacmaz_03 Насколько велик ваш массив? (и сколько у вас оперативной памяти). Возможно, вы заставите его работать, если снизите качество изображения, и в зависимости от размера изображения эта потеря качества может быть даже не видна глазу. Попробуйте
fig = plt.figure(dpi=10)
, ноdpi
, возможно, потребуется даже меньшее значение, поэтому попробуйте и меньшие значенияdpi
.4. Спасибо, я постараюсь прямо сейчас. Кстати, размеры массива составляют (475,5400,200), а моя оперативная память составляет 12 Гб.
5. @mehmet_kacmaz_03 . Я обновил свой ответ методом, который занимает очень мало оперативной памяти и намного быстрее, чем мой первоначальный ответ. Я надеюсь, что это будет работать и на вашем компьютере.