matplotlib: форматирует значения смещения оси к целым числам или определенному числу - PullRequest
89 голосов
/ 09 сентября 2010

У меня есть фигура matplotlib, на которую я наносю данные, которые всегда называются наносекундами (1e-9).На оси у, если у меня есть данные, которые десятки наносекунд, т.е.44e-9, значение на оси отображается как 4,4 с + 1e-8 в качестве смещения.Можно ли заставить ось показывать 44 со смещением + 1e-9?

То же самое относится и к моей оси x, где ось показывает + 5.54478e4, где я бы предпочел, чтобы она показала смещение+55447 (целое число, без десятичной дроби - значение здесь в днях).

Я пробовал пару вещей, как это:

p = axes.plot(x,y)
p.ticklabel_format(style='plain')

для оси X, но этоне работает, хотя я, вероятно, использую его неправильно или неправильно истолковываю что-то из документов. Может ли кто-нибудь указать мне правильное направление?

Спасибо, Джонатан

Problem illustration


Я пытался что-то сделать с форматерами, но пока не нашел решения ...:

myyfmt = ScalarFormatter(useOffset=True)
myyfmt._set_offset(1e9)
axes.get_yaxis().set_major_formatter(myyfmt)

и

myxfmt = ScalarFormatter(useOffset=True)
myxfmt.set_portlimits((-9,5))
axes.get_xaxis().set_major_formatter(myxfmt)

На заметку, яЯ на самом деле запутался в том, где находится объект 'число смещения' ... является ли он частью главных / второстепенных тиков?

Ответы [ 8 ]

97 голосов
/ 11 июля 2011

У меня была точно такая же проблема, и эти две строки устранили проблему:

y_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False)
ax.yaxis.set_major_formatter(y_formatter)
34 голосов
/ 10 сентября 2010

Гораздо более простым решением является простая настройка меток.Возьмите этот пример:

from pylab import *

# Generate some random data...
x = linspace(55478, 55486, 100)
y = random(100) - 0.5
y = cumsum(y)
y -= y.min()
y *= 1e-8

# plot
plot(x,y)

# xticks
locs,labels = xticks()
xticks(locs, map(lambda x: "%g" % x, locs))

# ytikcs
locs,labels = yticks()
yticks(locs, map(lambda x: "%.1f" % x, locs*1e9))
ylabel('microseconds (1E-9)')

show()

alt text

Обратите внимание, что в случае оси Y я умножил значения на 1e9, затем упомянул эту константу в метке y


РЕДАКТИРОВАТЬ

Другой вариант - подделать множитель экспоненты, вручную добавив его текст в верхнюю часть графика:

locs,labels = yticks()
yticks(locs, map(lambda x: "%.1f" % x, locs*1e9))
text(0.0, 1.01, '1e-9', fontsize=10, transform = gca().transAxes)

РЕДАКТИРОВАТЬ2

Также вы можете отформатировать значение смещения по оси X таким же образом:

locs,labels = xticks()
xticks(locs, map(lambda x: "%g" % x, locs-min(locs)))
text(0.92, -0.07, "+%g" % min(locs), fontsize=10, transform = gca().transAxes)

alt text

28 голосов
/ 09 сентября 2010

Вы должны создать подкласс ScalarFormatter, чтобы сделать то, что вам нужно ... _set_offset просто добавляет константу, вы хотите установить ScalarFormatter.orderOfMagnitude.К сожалению, ручная установка orderOfMagnitude ничего не даст, так как она сбрасывается при вызове экземпляра ScalarFormatter для форматирования меток оси.Это не должно быть так сложно, но я не могу найти более простой способ сделать именно то, что вы хотите ... Вот пример:

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

class FixedOrderFormatter(ScalarFormatter):
    """Formats axis ticks using scientific notation with a constant order of 
    magnitude"""
    def __init__(self, order_of_mag=0, useOffset=True, useMathText=False):
        self._order_of_mag = order_of_mag
        ScalarFormatter.__init__(self, useOffset=useOffset, 
                                 useMathText=useMathText)
    def _set_orderOfMagnitude(self, range):
        """Over-riding this to avoid having orderOfMagnitude reset elsewhere"""
        self.orderOfMagnitude = self._order_of_mag

# Generate some random data...
x = np.linspace(55478, 55486, 100) 
y = np.random.random(100) - 0.5
y = np.cumsum(y)
y -= y.min()
y *= 1e-8

# Plot the data...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, 'b-')

# Force the y-axis ticks to use 1e-9 as a base exponent 
ax.yaxis.set_major_formatter(FixedOrderFormatter(-9))

# Make the x-axis ticks formatted to 0 decimal places
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.0f'))
plt.show()

, который дает что-то вроде: alt text

Принимая во внимание, что форматирование по умолчанию будет выглядеть следующим образом: alt text

Надеюсь, что это немного поможет!

Редактировать: Во всяком случае, я не знаю, где находится метка смещениялибо ... Было бы немного проще просто установить его вручную, но я не мог понять, как это сделать ... У меня такое ощущение, что должен быть более простой способ, чем все это.Это работает, хотя!

11 голосов
/ 02 февраля 2011

Аналогично ответу Амро, вы можете использовать FuncFormatter

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

# Generate some random data...
x = np.linspace(55478, 55486, 100) 
y = np.random.random(100) - 0.5
y = np.cumsum(y)
y -= y.min()
y *= 1e-8

# Plot the data...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, 'b-')

# Force the y-axis ticks to use 1e-9 as a base exponent 
ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: ('%.1f')%(x*1e9)))
ax.set_ylabel('microseconds (1E-9)')

# Make the x-axis ticks formatted to 0 decimal places
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '%.0f'%x))
plt.show()
5 голосов
/ 10 января 2014

Решение Гонсало начало работать для меня после добавления set_scientific(False):

ax=gca()
fmt=matplotlib.ticker.ScalarFormatter(useOffset=False)
fmt.set_scientific(False)
ax.xaxis.set_major_formatter(fmt)
5 голосов
/ 07 сентября 2013

Я думаю, что более элегантный способ - использовать средство форматирования тикеров. Вот пример для xaxis и yaxis:

from pylab import *
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

majorLocator   = MultipleLocator(20)
xFormatter = FormatStrFormatter('%d')
yFormatter = FormatStrFormatter('%.2f')
minorLocator   = MultipleLocator(5)


t = arange(0.0, 100.0, 0.1)
s = sin(0.1*pi*t)*exp(-t*0.01)

ax = subplot(111)
plot(t,s)

ax.xaxis.set_major_locator(majorLocator)
ax.xaxis.set_major_formatter(xFormatter)
ax.yaxis.set_major_formatter(yFormatter)

#for the minor ticks, use no labels; default NullFormatter
ax.xaxis.set_minor_locator(minorLocator)
4 голосов
/ 24 июля 2017

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

matplotlib.rcParams['axes.formatter.useoffset'] = False
1 голос
/ 29 июня 2013

Для второй части, без ручного сброса всех тиков, это было мое решение:

class CustomScalarFormatter(ScalarFormatter):
    def format_data(self, value):
        if self._useLocale:
            s = locale.format_string('%1.2g', (value,))
        else:
            s = '%1.2g' % value
        s = self._formatSciNotation(s)
        return self.fix_minus(s)
xmajorformatter = CustomScalarFormatter()  # default useOffset=True
axes.get_xaxis().set_major_formatter(xmajorformatter)

очевидно, что вы можете установить строку форматирования на что хотите.

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