Рисование логарифмического графика на квадратной области графика в matplotlib

Я хотел бы нарисовать график с логарифмической осью y и линейной осью x на квадратной области графика в matplotlib. Я могу рисовать на квадратах как линейно-линейные, так и логарифмические графики, но используемый мной метод Axes.set_aspect(...) не реализован для логарифмических графиков. Есть ли хороший обходной путь?


линейно-линейный сюжет на квадрате:

from pylab import *
x = linspace(1,10,1000)
y = sin(x)**2+0.5
plot (x,y)
ax = gca()
data_aspect = ax.get_data_ratio()
ax.set_aspect(1./data_aspect)
show()

Квадратный линейно-линейный график


логарифмический график на квадрате:

from pylab import *
x = linspace(1,10,1000)
y = sin(x)**2+0.5
plot (x,y)
ax = gca()
ax.set_yscale("log")
ax.set_xscale("log")
xmin,xmax = ax.get_xbound()
ymin,ymax = ax.get_ybound()
data_aspect = (log(ymax)-log(ymin))/(log(xmax)-log(xmin))
ax.set_aspect(1./data_aspect)
show()

квадратный логарифмический график


Но когда я пробую это с логарифмическим графиком, я получаю не квадратную площадь, а предупреждение

from pylab import *
x = linspace(1,10,1000)
y = sin(x)**2+0.5
plot (x,y)
ax = gca()
ax.set_yscale("log")
xmin,xmax = ax.get_xbound()
ymin,ymax = ax.get_ybound()
data_aspect = (log(ymax)-log(ymin))/(xmax-xmin)
ax.set_aspect(1./data_aspect)
show()

выдает предупреждение:

axes.py:1173: UserWarning: aspect is not supported for Axes with xscale=linear, yscale=log

неквадратный логлинейный график


Есть ли хороший способ получить квадратно-логарифмические графики, несмотря на отсутствие поддержки в Axes.set_aspect?


person Markus    schedule 02.07.2014    source источник


Ответы (1)


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

Вы можете использовать ax.set_position для установки относительного (по отношению к фигуре) размера и положения графика. Чтобы использовать его в вашем случае, нам нужно немного математики:

from pylab import *

x = linspace(1,10,1000)
y = sin(x)**2+0.5
plot (x,y)
ax = gca()
ax.set_yscale("log")

# now get the figure size in real coordinates:
fig  = gcf()
fwidth = fig.get_figwidth()
fheight = fig.get_figheight()

# get the axis size and position in relative coordinates
# this gives a BBox object
bb = ax.get_position()

# calculate them into real world coordinates
axwidth = fwidth * (bb.x1 - bb.x0)
axheight = fheight * (bb.y1 - bb.y0)

# if the axis is wider than tall, then it has to be narrowe
if axwidth > axheight:
    # calculate the narrowing relative to the figure
    narrow_by = (axwidth - axheight) / fwidth
    # move bounding box edges inwards the same amount to give the correct width
    bb.x0 += narrow_by / 2
    bb.x1 -= narrow_by / 2
# else if the axis is taller than wide, make it vertically smaller
# works the same as above
elif axheight > axwidth:
    shrink_by = (axheight - axwidth) / fheight
    bb.y0 += shrink_by / 2
    bb.y1 -= shrink_by / 2

ax.set_position(bb)

show()

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

import matplotlib.pyplot as plt

pylab как нечетная смесь импорта numpy и matplotlib, созданная для облегчения интерактивного IPython использования. (Я тоже им пользуюсь.)

person DrV    schedule 02.07.2014