Использование библиотеки Matplotlib. Как менять положение легенды

Немного рекламы

Введение

В статье Использование библиотеки Matplotlib. Как отобразить легенду было перечислено несколько способов создания легенды для графиков (под легендой понимается прямоугольная область на графике, в которой показывается, какая линия чему соответствует). Напомню, что для создания описания линий, мы можем использовать параметр label функции pylab.plot, добавляя таким образом описание для каждой линии, а можем передать список строк с описаниями в функцию pylab.legend. На мой взгляд предпочтительней использовать первый вариант, чтобы оформление линий и их названия устанавливались в одном месте, ведь вызов pylab.legend может быть далеко в коде от вызова pylab.plot. В этой статье мы рассмотрим способы перемещения легенды в окне.

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

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.  
  29.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  30.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  31.  
  32.     # !!! Добавим легенду
  33.     pylab.legend ()
  34.  
  35.     pylab.grid()
  36.     pylab.show()

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

Положение легенды

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

  1. Строкой.
  2. Целочисленным значением.
  3. Кортежем из двух значений, задающих координаты легенды.

Первые два пункта действуют одинаково. В библиотеке Matplotlib существуют строковые константы и соответствующие им целочисленные константы, которые описывают, где должна располагаться легенда. Эти константы приведены в следующей таблице:

'best'0
'upper right'1
'upper left'2
'lower left'3
'lower right'4
'right'5
'center left'6
'center right'7
'lower center'8
'upper center'9
'center'10

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

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.  
  29.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  30.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  31.  
  32.     # !!! Добавим легенду
  33.     pylab.legend (loc='lower left')
  34.  
  35.     pylab.grid()
  36.     pylab.show()

Легенда переместилась в соответствующий угол:

Аналогичного результата мы достигнем, если заменим строку pylab.legend (loc='lower left') на pylab.legend (loc=3)

Вы, наверное, обратили внимание на константу 'best' . Эта строка (и соответствующее ей целочисленное значение) предназначена для того, чтобы библиотека Matplotib сама определила, куда лучше переместить легенду. Посмотрим, где окажется легенда, если мы заменим строку pylab.legend (loc='lower left') на pylab.legend (loc='best') или pylab.legend (loc=0):

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.  
  29.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  30.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  31.  
  32.     # !!! Добавим легенду
  33.     pylab.legend (loc=0)
  34.  
  35.     pylab.grid()
  36.     pylab.show()

Результат выглядит следующим образом:

По-моему, очень разумное расположение легенды.

Точное указание координат легенды

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

Координаты мы тоже можем указать, если передадим их в виде кортежа двух чисел в качестве значения того же параметра loc. Координаты являются нормированными, т.е. точка (0.0, 0.0) соответствует левому нижнему углу графика (не окна, а той области, где отображается сам график), а точка (1.0, 1.0) - правому верхнему углу. Если в качестве значения параметра loc передается кортеж, то это означает, что в указанные нормированные координаты будет помещен левый нижний угол легенды. В принципе, легенда может вылезать за пределы графика.

Исправим 33-ю строку предыдущего исходника на следующую (остальной код остается без изменений):

        pylab.legend (loc=(0.0, 0.0))

Легенда переместилась в соответствующее положение:

Или переместим легенду в правый верхний угол (я долго "прицеливался", чтобы попасть в нужные координаты):

        pylab.legend (loc=(0.743, 0.865))

Зазор между осями и легендой

Вы, наверное, обратили внимание, что когда мы устанавливаем положение легенды с помощью параметра loc, в случае, когда он принимает строковые или целочисленные значения, между легендой и осями графика остается зазор. Его величина настраивается с помощью параметра borderaxespad. Например, следующий код не только устанавливает легенду в левый верхний угол, но и совмещает границы легенды с границами графика, передавая в качестве значения borderaxespad значение 0. Эта величина задается в неких условных единицах, а точнее в единицах, в которых задаются размеры шрифтов.

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.  
  29.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  30.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  31.  
  32.     # !!! Добавим легенду
  33.     pylab.legend (loc=u'upper left', borderaxespad=0)
  34.  
  35.     pylab.grid()
  36.     pylab.show()

Результат выглядит следующим образом:

"Широкая" легенда

В функцию legend можно передать также параметр mode, который может принимать значение либо None - это значение по умолчанию -, либо строку 'expand' - это будет означать, что легенду надо расширить на всю ширину графика. Скорее всего это будет полезно в том случае, если у вас легенда будет располагаться либо за пределами графика, либо в легенде будут описываться несколько кривых, причем они будут располагаться в строку (благодаря использованию параметра ncol). Это показано в следующем примере:

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.     ylist3 = [func (x * 0.6) for x in xlist]
  29.  
  30.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  31.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  32.     pylab.plot (xlist, ylist3, 'r-', label = 'f(0.6 * x)')
  33.  
  34.     # !!! Добавим легенду
  35.     pylab.legend (loc=u'upper center',
  36.                   mode='expand',
  37.                   borderaxespad=0,
  38.                   ncol=3)
  39.  
  40.     pylab.grid()
  41.     pylab.show()

В результате окно с графиком будет выглядеть следующим образом:

Разрешение перемещения легенды с помощью мышки

Если мы заранее не можем предсказать, где легенда будет смотреться лучше, мы можем разрешить пользователю ее перемещать самостоятельно. Для этого нужно сначала получить экземпляр класса matplotlib.legend.Legend (см. статью Применение объектно-ориентированного стиля), который возвращается функцией pylab.legend(), а затем для полученного экземпляра класса вызвать метод draggable, передав ему в качестве параметра True:

  1. #!/usr/bin/env python
  2. # -*- coding: UTF-8 -*-
  3.  
  4. import math
  5.  
  6. import pylab
  7. from matplotlib import mlab
  8.  
  9.  
  10. def func (x):
  11.     return 1.0 if x == 0 else math.sin (x) / x
  12.  
  13.  
  14. if __name__ == '__main__':
  15.     # Интервал изменения переменной по оси X
  16.     xmin = -55.0
  17.     xmax = 20.0
  18.  
  19.     # Шаг между точками
  20.     dx = 0.01
  21.  
  22.     # Создадим список координат по оси X на отрезке [-xmin; xmax], включая концы
  23.     xlist = mlab.frange (xmin, xmax, dx)
  24.  
  25.     # Вычислим значение функции в заданных точках
  26.     ylist1 = [func (x) for x in xlist]
  27.     ylist2 = [func (x * 0.2) for x in xlist]
  28.  
  29.     pylab.plot (xlist, ylist1, 'b-', label = 'f(x)')
  30.     pylab.plot (xlist, ylist2, 'g--', label = 'f(0.2 * x)')
  31.  
  32.     # !!! Добавим легенду
  33.     legend = pylab.legend ()
  34.  
  35.     # Разрешим перемещать легенду
  36.     legend.draggable (True)
  37.  
  38.     pylab.grid()
  39.     pylab.show()

Теперь пользователь сможет перемещать легенду, захватывая ее мышкой:

Заключение

Мы рассмотрели почти все способы расположение легенды на графике. "Почти", потому что остался не рассмотренным еще один параметр bbox_to_anchor, задающий прямоугольную область, относительно которой будет выравниваться легенда с помощью параметра loc. На мой взгляд этим параметром пользоваться менее удобно по сравнению с явным заданием координат с помощью того же параметра loc.

Надеюсь, что эта статья будет вам полезна. Жду ваших оценок, дополнений и комментариев. :)

Другие статьи про Matplotlib

Немного рекламы

Вы можете подписаться на новости сайта через RSS, Группу Вконтакте или Канал в Telegram.
5 stars

Рейтинг 5.0/5. Всего 2 голос(а, ов)




Подписаться на комментарии
Автор:
Тема:
 Ваш комментарий
 
 
Введите код 356