matplotlib: форматування значень зміщення осі до цілих чисел або конкретного числа


92

У мене є цифра matplotlib, для якої я будую дані, які завжди називають наносекундами (1e-9). На осі y, якщо у мене є дані, які складають десятки наносекунд, тобто. 44e-9, значення на осі відображається як 4.4 із зміщенням + 1e-8. Чи є спосіб змусити вісь показувати 44 зі зміщенням + 1e-9?

Те саме стосується моєї осі х, де вісь показує + 5.54478e4, де я волів би, щоб вона мала зміщення +55447 (ціле число, без десяткової - значення тут у днях).

Я спробував кілька таких речей:

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

для осі х, але це не працює, хоча я, мабуть, використовую її неправильно або неправильно трактую щось із документів, може хтось вкаже мене в правильному напрямку?

Дякую, Джонатане

Ілюстрація проблеми


Я спробував щось зробити із форматорами, але поки не знайшов жодного рішення ...:

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
Ви пробували set_units? matplotlib.sourceforge.net/api/… (я не можу спробувати, бо у мене тут немає matplotlib.)
Катріель

1
Я перевірив функцію set_units, і вона здається набагато складнішою, ніж потрібно (потрібно написати / додати додатковий модуль ?? - basic_units?). Повинен бути спосіб просто редагувати формат галочки. Функція units / set_unit здається більш схожою на лінію перетворення одиниць. Дякую за підказку, але це призвело мене до деяких інших рішень, які я шукаю зараз!
Джонатан,

1
будь ласка, розгляньте rcParamsможливість вимкнути, якщо вимкнено за замовчуванням: rcParams["axes.formatter.useoffset"] = Falseяк тут: stackoverflow.com/questions/24171064/…
Руггеро Турра

Відповіді:


100

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

from matplotlib.ticker import ScalarFormatter

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

1
Це швидка і проста відповідь. Дякую.
maxm

6
ax.get_yaxis().get_major_formatter().set_useOffset(False)
Однокласник

3
для таких from matplotlib.ticker import ScalarFormatterнубів, як я, не забувайте, щоб код @Gonzalo працював, або просто використовуйте рішення
@Dataman

36

Набагато простішим рішенням є проста настройка міток галочок. Візьмемо цей приклад:

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()

текст заміщення

Зверніть увагу, як у випадку з віссю 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

Також ви можете відформатувати значення зміщення осі х таким же чином:

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)

текст заміщення


Спочатку я саме це робив. На жаль, я не зміг знайти простий спосіб встановити / показати множник осі (за винятком того, що явно помістив його в мітку осі y, як це зробили ви). Якщо ви не проти того, щоб не мати мітки множника осі, це простіший спосіб. У будь-якому випадку, +1 від мене.
Джо Кінгтон,

1
@ Joe Kington: ви можете додати його вручну як текст ... див. Редагування вище :)
Amro

Чудово! Я спробую ваш підхід із мітками для осі х. Я візьму слово першого значення x, потім видалю його з кожного значення x і додаю "+ minxval" як мітку. Я не можу зрозуміти, як ще відформатувати зміщення x-tick. Я добре з величиною зміщення, мені просто потрібно, щоб він відображався як неекспоненціальне значення.
Джонатан,

Ого. Чудова робота в тому, щоб показати, як ви дійсно можете взяти під контроль matplotlib і налаштувати його відповідно до своїх потреб, і справді, і трохи пізазувати свої ділянки.
physicsmichael

Як ви змінюєте розмір шрифту 1e-9 на малюнку?
пропозиція не може відмовити

30

Вам потрібно підклас, 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()

Що дає щось на зразок: текст заміщення

Тоді як форматування за замовчуванням буде виглядати так: текст заміщення

Сподіваюся, це трохи допоможе!

Редагувати: для чого це також, я не знаю, де міститься мітка зміщення ... Було б трохи простіше просто встановити її вручну, але я не міг зрозуміти, як це зробити ... У мене таке відчуття що повинен бути простіший спосіб, ніж усе це. Хоча це працює!


Дякую! Підкласифікація ScalarFormatter чудово працює! Але, мабуть, я чітко не заявив, що хочу для осі х. Я хотів би зберегти зміщення для осі х, але відформатуйте значення зміщення, щоб воно не відображалося як показник.
Джонатан,

Це єдиний метод, який працював у мене! Дякую :)
Ocean Scientist

11

Подібно до відповіді Амро, ви можете використовувати 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

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

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


4

Я думаю, що більш елегантний спосіб - це використовувати програму форматування тикерів. Ось приклад як для осей, так і для осей:

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)

1
Це не дає відповіді на запитання, як саме вказати зсув та / або фактор, що використовується в наукових позначеннях .
sodd

@nordev Навіть якщо моя відповідь конкретно не відповідає на питання, це все одно дає підказку. Повідомлення полягає в тому, що ви можете вибрати інший форматтер і отримати бажане замість дати з мого прикладу. У науковому світі юліанський день є нормою, або ви можете використовувати дату, як у моєму прикладі. Що я намагався запропонувати, це те, що можна застосувати інший підхід. Іноді може бути задане питання, оскільки на даний момент людина не має кращої ідеї. Не можна відкидати альтернативні рішення або не поважати їх. Загалом, я не заслужив -1 голос.
Богдан

2

Для другої частини, без ручного скидання всіх галочок знову, це було моє рішення:

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)

очевидно, що ви можете встановити рядок формату як завгодно.


На жаль, я не досліджував, як встановити множник як першу частину вашого запитання.
astrojuanlu
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.