Как установить точное значение с плавающей точкой в ​​качестве коэффициента масштабирования для моих ограничений по оси Y в Matplotlib? - PullRequest
0 голосов
/ 25 марта 2020

Число 1.67845714e-12 - важный результат моего физического проекта. Я хочу построить графики, где предел оси Y вращается вокруг этого результата как коэффициент масштабирования.

В следующем примере:

import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random 

x = np.arange(0,100)
y = np.zeros(len(x))

for i in range(len(x)):
    y[i] = 1.67845714e-12*random.random() - (4.20e-14)*x[i]

plt.ylim(float(-3*1.67845714e-12), float(3*1.67845714e-12)) #The important line 
plt.plot(x,y)

Получившийся участок имеет ось Y идет от -5*e-12 до 5*e-12 вместо оси Y от -3*1.67845714e-12 до 3*1.67845714e-12

Как мне заставить Matplotlib отображать шаг 1.67845714e-12 на верхний левый угол графика со шкалой от -3 до 3 отображается на оси у, как я и предполагал? И если это невозможно из-за того, что, например, шаг слишком длинный, могу ли я дать своему шагу псевдоним (например, «Результат») для выполнения этой работы?

Я пытался использовать другие команды, такие как ax.set_yticks(), ax=plt.gta() или ax.set_ylim() но ничего из того, что я искал, похоже не работает.

1 Ответ

1 голос
/ 26 марта 2020

Я пытаюсь ответить на основании того, что, как я понял, вы хотели сделать. На мой взгляд, вы хотите иметь ось y от -3*1.67845714e-12 до 3*1.67845714e-12, но каждый шаг / тик будет иметь размер 1.67845714e-12.

Примечание. Я создал переменную с именем scalingFactor для хранения 1.67845714e-12. Я думаю, что это отвечает на один из ваших вопросов. Тогда вы можете использовать его вместо записи целого числа.

Хорошо, чтобы сгенерировать тики, чтобы вы могли использовать функцию numpy.arange(inf, sup, step). Возвращает равномерно распределенные значения в заданном интервале [inf;sup). Таким образом, мы собираемся генерировать тики от -3*scalingFactor до 3*scalingFactor, используя шаг 1.67845714e-12. В коде вы можете заметить, что sup=4*scalingFactor. Это потому, что numpy.arange() исключает верхнюю границу интервала.

Чтобы получить целое число на оси и не округлить, вы можете заставить его иметь 8 десятичных знаков, используя plt.gca().yaxis.set_major_formatter(mtick.FormatStrFormatter('%.8e')). Эта функция форматирует метки для отметок оси и в этом случае использует этот формат строки %.8e.

import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random 
import matplotlib.ticker as mtick

x = np.arange(0,100)
y = np.zeros(len(x))

scalingFactor = 1.67845714e-12

for i in range(len(x)):
    y[i] = scalingFactor*random.random() - (4.20e-14)*x[i]

inf = -3*scalingFactor
sup = 4*scalingFactor

plt.plot(x, y)
plt.ylim(inf, sup)
plt.yticks(np.arange(inf, sup, scalingFactor))
plt.subplots_adjust(left=0.24) # Squash the plot from the left so the ticks labels can be seen
plt.gca().yaxis.set_major_formatter(mtick.FormatStrFormatter('%.8e')) 
plt.show()

Выходы

Output

РЕДАКТИРОВАТЬ: Ну, на самом деле я боролся с тем, что вы хотели, потому что мне никогда не нужно было этого делать. Однако я придумал очень ad-ho c решение для вашей проблемы, основанное на том, что вам нужно, потому что кажется, что все ваши данные будут в этом диапазоне, и вы хотели коэффициент масштабирования 1.67845714e-12.

Существуют классы форматирования, которые могут форматировать значения тиков и обрабатывать значения смещения (значение масштаба в верхнем левом углу). Таким образом, мы можем создать ModScalarFormatter, который наследует от ScalarFormatter и переопределить некоторые функции, чтобы вручную установить желаемое смещение и отметки, не позволяя matplotlib вычислить его:

import numpy as np
import matplotlib.pyplot as plt
plt.ion()
import random 
import math
import matplotlib.ticker as mtick

class ModScalarFormatter(mtick.ScalarFormatter):
    def __init__(self, useOffset=None, useMathText=None, useLocale=None):
        mtick.ScalarFormatter.__init__(self, useOffset, useMathText, useLocale)
        # Create the ticks we want
        self.ticks = [i for i in range(-3, 4)]

    def _set_offset(self, text):
        self.offset = text # Set the offset text we want

    def get_offset(self, txt=''):
        return self.offset # Return the offset value

    def __call__(self, x, pos=None):
        # The __call__ returns the tick on position `pos` from the
        # ticks we specified
        return self.ticks[pos]

x = np.arange(0,100)
y = np.zeros(len(x))

scalingFactor = 1.67845714e-12

for i in range(len(x)):
    y[i] = scalingFactor*random.random() - (4.20e-14)*x[i]

inf = -3*scalingFactor
sup = 3*scalingFactor

plt.plot(x, y)
plt.yticks(np.linspace(inf, sup, 7))

# Create and use a Custom Scalar Formatter Class
sf = ModScalarFormatter(useOffset=1.67845714e-12)
plt.gca().yaxis.set_major_formatter(sf)

plt.ylim(inf, sup)

plt.show()

Выходы: Ad-hoc solution

ПРИМЕЧАНИЕ : Я почти уверен, что должен быть более элегантный способ добиться этого, но это мой способ помочь вам и ad-ho c решение вашей конкретной проблемы c.

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

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