Легенда в отдельном сюжете и сетке - PullRequest
0 голосов
/ 13 ноября 2018

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

Внешний вид серии данных анимирован, но я бы не хотел, чтобы легенды были.

Моя идея состояла в том, чтобы нарисовать временной ряд в моей правой сетке с легендами и скрыть ряд данных. Но мое единственное решение - ax.set_visible (False), которое удаляет все.

Вот как выглядит скрипт (упрощенная версия):

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as anim
from matplotlib.gridspec import GridSpec

data = np.array([[1],[2],[3],[4]])
sett = np.array([1,2,3,4])

data1 = np.hstack((data,data*2, data*3, data*4))
data2 = np.hstack((3*data, 3*data/2, 3*data/3, 3*data/4))
df1 = pd.DataFrame(data = np.array(data1), index = [1,2,3,4], columns = 
sett).transpose()
df2 = pd.DataFrame(data = np.array(data2), index = [1,2,3,4], columns = 
sett).transpose()

gs1 = GridSpec(2,2)
gs1.update(left=0.05, right = 0.80, hspace = 0.05)
gs2 = GridSpec(3,1)
gs2.update(left=0.85, right = 0.98, hspace = 0.05)
figure = plt.figure()
plt.clf()
ax1 = plt.subplot(gs1[0,:])
ax2 = plt.subplot(gs1[1,0])
ax3 = plt.subplot(gs1[1,1], sharey = ax2)
ax4 = plt.subplot(gs2[:,0])
ax1.set_ylim(0,25)

label = ['s0', 's1', 's2', 's3', 's4']
ax4.plot(df1[1], df2[:])
ax4.legend(labels = label)

def make_frame(i):
    ct=sett[i]

    ax2.plot(df1[1], df1[ct])

    ax3.plot(df1[1], df2[ct])
    ax3.legend(labels = label)

ani = anim.FuncAnimation(figure, make_frame, frames = len(sett), 
                     interval =500, repeat = False)

plt.show()

Как удалить серию данных и сохранить легенду в gs2 / ax4?

Не беспокойтесь, я нанесу первый ряд данных дважды в ax2 и ax3 - это нормально в моем оригинальном сценарии. Однако - если кто-то может объяснить мне, почему, это очень ценится.

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

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

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as anim
from matplotlib.gridspec import GridSpec

data = np.array([1,2,3,4,5])

data1 = np.vstack((data,data*2, data*3, data*4))
data2 = np.vstack((3*data, 3*data/2, 3*data/3, 3*data/4))
df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)

sett = np.arange(len(df1.columns))

gs1 = GridSpec(2,2)
gs1.update(left=0.05, right = 0.80, hspace = 0.05)

figure = plt.figure()

ax1 = plt.subplot(gs1[0,:])
ax2 = plt.subplot(gs1[1,0])
ax3 = plt.subplot(gs1[1,1], sharey = ax2, sharex= ax2)

ax2.set_ylim(0,25)


lines1 = ax2.plot(*[[] for _ in range(len(sett)*2)])
lines2 = ax3.plot(*[[] for _ in range(len(sett)*2)])

label = ['s0', 's1', 's2', 's3', 's4']
ax1.legend(handles = lines1, labels=label, bbox_to_anchor=(1.05,1), loc="upper left")

def init():
    for line in lines1+lines2:
        line.set_data([],[])

def make_frame(i):
    ct=sett[i]
    lines1[i].set_data(df1.index, df1[ct])
    lines2[i].set_data(df1.index, df2[ct])
    ax2.relim()
    ax2.autoscale_view()

ani = anim.FuncAnimation(figure, make_frame, init_func=init, frames = len(sett), 
                     interval =500, repeat = False)
ani.save("anigif.gif", writer="imagemagick")
plt.show()

enter image description here

0 голосов
/ 13 ноября 2018

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

Мое решение состоит в том, чтобы вообще не создавать ax4.Вместо этого вы можете использовать bbox_to_anchor для перемещения положения легенды.Здесь я использую преобразование из ax1, чтобы установить местоположение относительно ax1, и перемещаю легенду немного за правый край и вверху ax1.

См. "легендаguide "для получения дополнительной информации .

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as anim
from matplotlib.gridspec import GridSpec

data = np.array([[1], [2], [3], [4]])
sett = np.array([1, 2, 3, 4])

data1 = np.hstack((data, data * 2, data * 3, data * 4))
data2 = np.hstack((3 * data, 3 * data / 2, 3 * data / 3, 3 * data / 4))
df1 = pd.DataFrame(data=np.array(data1), index=[1, 2, 3, 4], columns=sett).transpose()
df2 = pd.DataFrame(data=np.array(data2), index=[1, 2, 3, 4], columns=sett).transpose()

gs1 = GridSpec(2, 2)
gs1.update(left=0.05, right=0.80, hspace=0.05)
figure = plt.figure()
plt.clf()
ax1 = plt.subplot(gs1[0, :])
ax2 = plt.subplot(gs1[1, 0])
ax3 = plt.subplot(gs1[1, 1], sharey=ax2)

label = ['s0', 's1', 's2', 's3', 's4']


def make_frame(i):
    ct = sett[i]

    ax2.plot(df1[1], df1[ct])

    ax3.plot(df1[1], df2[ct])
    ax3.legend(labels=label, loc='upper left', bbox_to_anchor=(1.05, 1.), bbox_transform=ax1.transAxes)


ani = anim.FuncAnimation(figure, make_frame, frames=len(sett),
                         interval=500, repeat=False)

plt.show()

enter image description here

РЕДАКТИРОВАТЬ: используя прокси-художника для создания всех легенддо запуска анимации

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as anim
from matplotlib.gridspec import GridSpec

data = np.array([[1], [2], [3], [4]])
sett = np.array([1, 2, 3, 4])

data1 = np.hstack((data, data * 2, data * 3, data * 4))
data2 = np.hstack((3 * data, 3 * data / 2, 3 * data / 3, 3 * data / 4))
df1 = pd.DataFrame(data=np.array(data1), index=[1, 2, 3, 4], columns=sett).transpose()
df2 = pd.DataFrame(data=np.array(data2), index=[1, 2, 3, 4], columns=sett).transpose()

gs1 = GridSpec(2, 2)
gs1.update(left=0.05, right=0.80, hspace=0.05)

figure = plt.figure()
plt.clf()
ax1 = plt.subplot(gs1[0, :])
ax2 = plt.subplot(gs1[1, 0])
ax3 = plt.subplot(gs1[1, 1], sharey=ax2)

ax1.set_ylim(0, 25)

labels = ['s0', 's1', 's2', 's3', 's4']
colors = ['C0', 'C1', 'C2', 'C3', 'C4']
proxies = [plt.plot([], [], c=c)[0] for c in colors]
ax1.legend(proxies, labels, bbox_to_anchor=(1., 1.), loc="upper left")


def init_frame():
    pass


def make_frame(i):
    ct = sett[i]
    ax2.plot(df1[1], df1[ct], c=colors[i], label=labels[i])
    ax3.plot(df1[1], df2[ct], c=colors[i], label=labels[i])
    ax3.legend()


ani = anim.FuncAnimation(figure, make_frame, init_func=init_frame, frames=len(sett),
                         interval=500, repeat=False)

plt.show()

enter image description here

...