Matplotlib: значения смещения оси формата для целых чисел или определенного номера

У меня есть показатель matplotlib, который я рисую данными, которые всегда упоминаются как наносекунды (1е-9). По оси y, если у меня есть данные, составляющие десятки наносекунд, т.е. 44e-9, значение на оси показывает как 4.4 с a + 1e-8 как смещение. В любом случае, чтобы заставить ось показать 44 с смещением + 1e-9?

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

Я пробовал пару таких вещей:

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

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

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

Problem illustration


Я пробовал делать что-то с formatters, но еще не нашел решения...

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)

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

Ответ 1

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

y_formatter = matplotlib.ticker.ScalarFormatter(useOffset=False)
ax.yaxis.set_major_formatter(y_formatter)

Ответ 2

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

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)

EDIT2

Также вы можете отформатировать смещение по оси 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

Ответ 3

У вас есть подкласс ScalarFormatter, чтобы сделать то, что вам нужно... _set_offset просто добавляет константу, вы хотите установить ScalarFormatter.orderOfMagnitude. К сожалению, настройка вручную orderOfMagnitude не будет делать ничего, поскольку она reset, когда экземпляр 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

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

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

Ответ 4

Как и в ответе Amro, вы можете использовать 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

Я думаю, что более элегантным способом является использование форматирования тикера. Вот пример как для 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)

Ответ 6

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

ax=gca()
fmt=matplotlib.ticker.ScalarFormatter(useOffset=False)
fmt.set_scientific(False)
ax.xaxis.set_major_formatter(fmt)

Ответ 7

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

matplotlib.rcParams['axes.formatter.useoffset'] = False

Ответ 8

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

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)

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