Изменение частоты тиков на оси x или y в matplotlib?

477

Я пытаюсь исправить, как Python отображает мои данные.

Сказать

x = [0,5,9,10,15]

а также

y = [0,1,2,3,4]

Тогда я бы сделал:

matplotlib.pyplot.plot(x,y)
matplotlib.pyplot.show()

и отметки по оси x нанесены с интервалами 5. Можно ли сделать так, чтобы интервалы показывали 1?

Дакс Фелиз
источник
6
Хотя слово «галочки» здесь уместно, смена галочки на размер шага определенно поможет новичкам в этом вопросе.
Sibbs Gambling
9
Тесно связанный вопрос: stackoverflow.com/questions/6682784/… и отличное решение:pyplot.locator_params(nbins=4)
Доктор Ян-Филипп Герке
К сожалению,
nbins

Ответы:

584

Вы можете явно указать, где вы хотите поставить отметки plt.xticks:

plt.xticks(np.arange(min(x), max(x)+1, 1.0))

Например,

import numpy as np
import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(np.arange(min(x), max(x)+1, 1.0))
plt.show()

( np.arangeна rangeвсякий случай был использован вместо функции Python min(x)и max(x)являются плавающими вместо целых.)


Функция plt.plot(или ax.plot) автоматически устанавливает значения по умолчанию xи yограничения. Если вы хотите сохранить эти ограничения и просто изменить размер шага отметок, вы можете использовать, ax.get_xlim()чтобы узнать, какие ограничения уже установлены Matplotlib.

start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, stepsize))

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

ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))

Вот работающий пример:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
start, end = ax.get_xlim()
ax.xaxis.set_ticks(np.arange(start, end, 0.712123))
ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%0.1f'))
plt.show()
unutbu
источник
72
Нет ли способа заставить его решить свои собственные ограничения, а просто изменить размер шага? Этот метод не очень хорош, если min что-то вроде 3523.232512!
Короне
3
@Corone, Прошло много времени с тех пор, как вы спросили, но я разместил ответ ниже, который позволяет легко контролировать размер шага, все еще используя автоматическое определение границ.
Jthomas
3
Обратите внимание, что для отображения последней отметки требуется знак « +1in» plt.xticks(np.arange(min(x), max(x)+1, 1.0)).
Алекс Виллисон
1
Да, np.arange(start, stop)генерирует значения в полуоткрытом интервале [start, stop), включая, startно исключая stop. Так что я использовал, max(x)+1чтобы убедиться, что max(x)включено.
unutbu
4
есть ли эквивалент для даты и времени, например plt.xticks(np.arange(min(dates), max(dates)+0.1,0.1)? кажется, только строит год
WBM
207

Другой подход заключается в установке локатора оси:

import matplotlib.ticker as plticker

loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)

Есть несколько различных типов локатора в зависимости от ваших потребностей.

Вот полный пример:

import matplotlib.pyplot as plt
import matplotlib.ticker as plticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]
fig, ax = plt.subplots()
ax.plot(x,y)
loc = plticker.MultipleLocator(base=1.0) # this locator puts ticks at regular intervals
ax.xaxis.set_major_locator(loc)
plt.show()
robochat
источник
7
Это не работает, как ожидалось. В частности, при использовании дат не используются соответствующие даты.
Крис Фоннесбек
35
При использовании дат вы должны использовать методы в модуле matplotlib.dates. Напримерmatplotlib.dates.AutoDateLocator()
робочать
3
Это сработало, как и ожидалось для меня, с датами. Это решение намного проще, чем принятое.
Пабло Суау
Что на base=1.0самом деле означает / делает?
Джавадба
base = 1.0 означает, что найдется локатор для каждого целого числа. В документации сказано, что MultipleLocator «Установите [s] галочку на каждое целое число, кратное основанию в пределах интервала просмотра». Так что, если base = 2, тогда будет четное число для четных чисел, и я думаю, что вы можете поставить base = 2.5.
робочать
124

Мне нравится это решение (из книги рецептов Matplotlib Plotting ):

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker

x = [0,5,9,10,15]
y = [0,1,2,3,4]

tick_spacing = 1

fig, ax = plt.subplots(1,1)
ax.plot(x,y)
ax.xaxis.set_major_locator(ticker.MultipleLocator(tick_spacing))
plt.show()

Это решение дает вам возможность явно контролировать интервал между тиками с помощью заданного номера ticker.MultipleLocater(), позволяет автоматически определять лимиты и легко читается позже.

jthomas
источник
3
Способ сделать это без явного расчета тиков!
Зельфир Кальцталь
4
Это тот же ответ, что и этот . Не имеет смысла добавлять идентичный ответ два года спустя.
Важное значение
6
Хороший улов. Я не узнал их как одинаковые, когда разместил ответ. Тем не менее, я думаю, что эту презентацию немного легче понять.
17
Ссылка на книгу в этом ответе также является полезным источником дополнительной информации.
Стивен Хоуэлл,
1
Это тот же ответ, что и у робочата, который пришел тремя годами ранее.
MERose
90

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

ax.set_xticks(ax.get_xticks()[::2])
glopes
источник
3
Это единственный обобщенный ответ для разных типов
тиков
2
Снимите нецелочисленные ax.set_xticks([tick for tick in ax.get_xticks() if tick % 1 == 0])
галочки
Много подробных решений выше, но я согласен, что это наиболее кратко. Вы даже можете извлечь длину ax.get_xticks () и установить частоту срезов на эту длину, деленную на количество необходимых тиков.
Iain D
Я думаю, что это лучший ответ. Большинство других ответов слишком сложны и их трудно применять / обобщать. Спасибо!
Seankala
2
Это может только уменьшить количество палочек, тогда как в вопросе (и моей цели, как я его нашел) было увеличить его.
Алексей
36

Это немного хакерский, но, безусловно, самый чистый / легкий для понимания пример, который я нашел для этого. Это из ответа на SO здесь:

Самый простой способ скрыть каждую метку nth в цветовой панели matplotlib?

for label in ax.get_xticklabels()[::2]:
    label.set_visible(False)

Затем вы можете зациклить надписи, устанавливая их видимыми или нет в зависимости от плотности, которую вы хотите.

edit: обратите внимание, что иногда matplotlib устанавливает метки == '', поэтому может показаться, что метка отсутствует, хотя на самом деле она ничего не отображает. Чтобы убедиться, что вы просматриваете фактические видимые метки, вы можете попробовать:

visible_labels = [lab for lab in ax.get_xticklabels() if lab.get_visible() is True and lab.get_text() != '']
plt.setp(visible_labels[::2], visible=False)
choldgraf
источник
3
Это самое простое и универсальное решение. Небольшая корректировка: обычно ax.get_xticklabels()[1::2]ярлыки скрыты.
Jolvi
Это не работает с matplotlib.finance.candlestick2
BCR
@BCR может случиться так, что некоторые xticklabels просто установлены ''так, что, когда вы проходите через них, вы делаете xticklabels пустыми невидимыми (что не повлияет на визуализацию, но может означать, что вы не тянете правильные метки). Вы можете попробовать: vis_labels = [label for label in ax.get_xticklabels() if label.get_visible() is True]; plt.setp(vis_labels[::2], visible==False)
choldgraf
15

Это старая тема, но я спотыкаюсь об этом время от времени и сделал эту функцию. Это очень удобно:

import matplotlib.pyplot as pp
import numpy as np

def resadjust(ax, xres=None, yres=None):
    """
    Send in an axis and I fix the resolution as desired.
    """

    if xres:
        start, stop = ax.get_xlim()
        ticks = np.arange(start, stop + xres, xres)
        ax.set_xticks(ticks)
    if yres:
        start, stop = ax.get_ylim()
        ticks = np.arange(start, stop + yres, yres)
        ax.set_yticks(ticks)

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

gca().set_ylim(top=new_top) # for example

и снова запустите функцию перенастройки.

Tompa
источник
11

Я разработал не элегантное решение. Учтите, что у нас есть ось X, а также список меток для каждой точки в X.

Пример:
import matplotlib.pyplot as plt

x = [0,1,2,3,4,5]
y = [10,20,15,18,7,19]
xlabels = ['jan','feb','mar','apr','may','jun']
Допустим, я хочу показывать метки только для 'feb' и 'jun'
xlabelsnew = []
for i in xlabels:
    if i not in ['feb','jun']:
        i = ' '
        xlabelsnew.append(i)
    else:
        xlabelsnew.append(i)
Хорошо, теперь у нас есть поддельный список ярлыков. Сначала мы подготовили оригинальную версию.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabels,rotation=45)
plt.show()
Теперь модифицированная версия.
plt.plot(x,y)
plt.xticks(range(0,len(x)),xlabelsnew,rotation=45)
plt.show()
Deninhos
источник
6

если вы просто хотите установить интервал простой однострочный с минимальным шаблоном:

plt.gca().xaxis.set_major_locator(plt.MultipleLocator(1))

также легко работает для мелких тиков:

plt.gca().xaxis.set_minor_locator(plt.MultipleLocator(1))

немного аппетитно, но довольно компактно

Гэри Стил
источник
2
xmarks=[i for i in range(1,length+1,1)]

plt.xticks(xmarks)

Это сработало для меня

если вы хотите, чтобы тики между [1,5] (1 и 5 включительно), то замените

length = 5
Пиюш Гупта
источник
1
Кстати, вы могли бы просто написать xmarks = range(1, length+1, 1). уверен, что понимание списка излишне.
Нил
2

Чистая реализация Python

Ниже приведена чистая реализация на Python требуемой функциональности, которая обрабатывает любой числовой ряд (int или float) с положительными, отрицательными или смешанными значениями и позволяет пользователю указать желаемый размер шага:

import math

def computeTicks (x, step = 5):
    """
    Computes domain with given step encompassing series x
    @ params
    x    - Required - A list-like object of integers or floats
    step - Optional - Tick frequency
    """
    xMax, xMin = math.ceil(max(x)), math.floor(min(x))
    dMax, dMin = xMax + abs((xMax % step) - step) + (step if (xMax % step != 0) else 0), xMin - abs((xMin % step))
    return range(dMin, dMax, step)

Пример вывода

# Negative to Positive
series = [-2, 18, 24, 29, 43]
print(list(computeTicks(series)))

[-5, 0, 5, 10, 15, 20, 25, 30, 35, 40, 45]

# Negative to 0
series = [-30, -14, -10, -9, -3, 0]
print(list(computeTicks(series)))

[-30, -25, -20, -15, -10, -5, 0]

# 0 to Positive
series = [19, 23, 24, 27]
print(list(computeTicks(series)))

[15, 20, 25, 30]

# Floats
series = [1.8, 12.0, 21.2]
print(list(computeTicks(series)))

[0, 5, 10, 15, 20, 25]

# Step – 100
series = [118.3, 293.2, 768.1]
print(list(computeTicks(series, step = 100)))

[100, 200, 300, 400, 500, 600, 700, 800]

Образец использования

import matplotlib.pyplot as plt

x = [0,5,9,10,15]
y = [0,1,2,3,4]
plt.plot(x,y)
plt.xticks(computeTicks(x))
plt.show()

Участок образца использования

Обратите внимание, что ось X имеет целочисленные значения, все они равномерно распределены на 5, тогда как ось Y имеет другой интервал ( matplotlibповедение по умолчанию, поскольку галочки не были указаны).

Greenstick
источник