Как добавить галочки с постоянным интервалом на осях, длина которых варьируется? [Python] - PullRequest
5 голосов
/ 27 июня 2011

Чтобы упростить мою проблему (это не совсем так, но я предпочитаю простые ответы на простые вопросы):

У меня есть несколько 2D-карт, которые изображают прямоугольные области региона. Я хотел бы добавить на карту оси и отметки, чтобы показать расстояния на этой карте (с помощью matplotlib, поскольку старый код с ним), но проблема в том, что области имеют разные размеры. Я хотел бы поставить на оси красивые, четкие галочки, но ширина и высота карт могут быть любыми ...

Чтобы попытаться объяснить, что я имею в виду: допустим, у меня есть карта региона, размер которого составляет 4,37 км * 6,42 км. Я хочу, чтобы на 0, 1, 2, 3 и 4 км: с имелись отметки по оси X, а на 0, 1, 2, 3, 4, 5 и 6 км: с - по отметкам по оси y. Однако изображение и оси доходят чуть дальше, чем до 4 км и 6 км, поскольку область больше 4 км * 6 км.

Расстояние между клещами может быть постоянным, 1 км. Однако размеры карт довольно сильно различаются (скажем, между 5-15 км), и они являются значениями с плавающей точкой. Мой текущий скрипт знает размер области и может масштабировать изображение до правильного соотношения высоты и ширины, но как определить, куда ставить галочки?

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

Ответы [ 3 ]

5 голосов
/ 28 июня 2011

Просто установите для тикового локатора значение matplotlib.ticker.MultipleLocator(x), где x - необходимый интервал (например, 1,0 в приведенном выше примере).

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

x = np.arange(20)
y = x * 0.1

fig, ax = plt.subplots()
ax.plot(x, y)

ax.xaxis.set_major_locator(MultipleLocator(1.0))
ax.yaxis.set_major_locator(MultipleLocator(1.0))

# Forcing the plot to be labeled with "plain" integers instead of scientific notation
ax.xaxis.set_major_formatter(FormatStrFormatter('%i'))

plt.show()

Преимущество этого состоит в том, что независимо от того, как мы масштабируем или взаимодействуем с графиком, он всегда будет помечен галочками на 1 единицу. enter image description here

0 голосов
/ 29 июня 2011

Хорошо, я попробовал ваши версии, но, к сожалению, я не смог заставить их работать, так как были некоторые вещи, связанные с масштабированием и поиском в PDF, которые сильно смутили меня (и ваши предложения по коду).Но, протестировав их, я снова многому научился на python, спасибо!

Мне наконец удалось найти решение, которое не очень точное, но удовлетворяет мои потребности.Вот как я это сделал.

В моей версии один километр делится на подходящую целую константу с именем STEP_PART.Чем больше значение STEP_PART, тем точнее значения оси (и если оно слишком большое, ось становится грязной для чтения).Например, если STEP_PART равен 5, точность равна 1 км / 5 = 200 м, а метки ставятся на каждые 200 м.

STEP_PART = 5             # In the start of the program.

height = 6.42             # These are actually given elsewhere,
width = 4.37              # but just as example...

vHeight = range(0, int(STEP_PART*height), 1)  # Make tick vectors, now in format
                                              # 0, 1, 2... instead of 0, 0.2...
vWidth = range(0, int(STEP_PART*width), 1)    # Should be divided by STEP_PART 
                                              # later to get right values.

Чтобы избежать создания слишком большого количества меток оси (0, 1, 2... достаточно, 0, 0,2, 0,4 ... это слишком много), мы заменяем нецелые значения км строкой "".Одновременно мы делим целочисленные значения км на STEP_PART, чтобы получить правильные значения.

for j in range(len(vHeight)):
    if (j % STEP_PART != 0):
        vHeight[j] = ""
    else:
        vHeight[j] = int(vHeight[j]/STEP_PART)

for i in range(len(vWidth)):
    if (i % STEP_PART != 0):
        vWidth[i] = ""
    else:
        vWidth[i] = int(vWidth[i]/STEP_PART)

Позже, после создания графика и осей, таким образом ставятся галочки (например, ось x).Здесь x - фактическая ширина изображения, полученная с помощью команды shape () (я не совсем понимаю, как ... в коде, который я модифицирую, довольно много масштабирования и прочего).

xt = np.linspace(0,x-1,len(vWidth)+1) # For locating those ticks on the same distances.
locs, labels = mpl.xticks(xt, vWidth, fontsize=9) 

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

0 голосов
/ 27 июня 2011

Это должно дать вам отметки на всех целочисленных значениях в пределах текущих ограничений по оси x:

from matplotlib import pylab as plt
import math

# get values for the axis limits (unless you already have them)
xmin,xmax = plt.xlim()

# get the outermost integer values using floor and ceiling 
# (I need to convert them to int to avoid a DeprecationWarning),
# then get all the integer values between them using range
new_xticks = range(int(math.ceil(xmin)),int(math.floor(xmax)+1))
plt.xticks(new_xticks,new_xticks)
# passing the same argment twice here because the first gives the tick locations
# and the second gives the tick labels, which should just be the numbers

Повторите для оси y.

Из любопытства: какие галочки вы получаете по умолчанию?

...