Настроить сдвиг в смещении matplotlib - PullRequest
0 голосов
/ 13 декабря 2018

Этот вопрос относится к проблеме, с которой я сейчас сталкиваюсь.У меня есть некоторые данные, скажем [12.301, 12.318, 12.302], которые при построении графика приводят к смещению, отображаемому как +1.23e1.

. Я не возражаю против самого смещения, но эта экспоненциальная форма вместо простого написания 12.3не очень приятноМогу ли я каким-то образом заставить показатель степени появляться только для кратных трех степеней от десяти?1e3 вместо 1000 имеет смысл, 1e1 вместо 10 совсем нет.

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

1 Ответ

0 голосов
/ 14 декабря 2018

Немного поиска в сети и адаптации найденных ответов здесь , здесь и здесь плюс print(dir(ScalarFormatter)), я смогчтобы адаптировать первое связанное сообщение:

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

#from https://stackoverflow.com/a/45332730/2454357
def fexp(f):
    return int(np.floor(np.log10(abs(f)))) if f != 0 else 0

#from https://stackoverflow.com/a/45332730/2454357
def fman(f):
    return f/10**fexp(f)

#adapted from https://stackoverflow.com/a/3679918/2454357
class PowerMultipleOfThreeFormatter(ScalarFormatter):
    """Formats axis ticks using scientific notation with a constant order of 
    magnitude"""
    def __init__(self, useOffset=True, useMathText=False):
        ScalarFormatter.__init__(self, useOffset=useOffset, 
                                 useMathText=useMathText)

    def _set_orderOfMagnitude(self, range):
        """Over-riding this to avoid having orderOfMagnitude reset elsewhere"""
        exponent = fexp(range)
        if -3 < exponent < 3:
            self.orderOfMagnitude = 0
        else:
            new_exp = (exponent//3)*3
            self.orderOfMagnitude = new_exp


    def format_data(self, *args, **kwargs):

        ##make sure that format_data does everyting it shoud:
        super(PowerMultipleOfThreeFormatter, self).format_data(
            *args, **kwargs
        )

        ##compute the offset in the right format
        exponent = fexp(self.offset)
        mantissa = fman(self.offset)
        if -3 < exponent < 3:
            return '{:g}'.format(self.offset)

        new_exp = (exponent//3)*3
        factor = 10**new_exp

        ##from https://stackoverflow.com/a/2440786/2454357
        man_string = '{}'.format(self.offset/factor).rstrip('0').rstrip('.')
        return man_string+'e{}'.format(new_exp)

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

# Plot the data...
fig,axes = plt.subplots(nrows=2, ncols=2)
for ax, y0 in zip(axes.ravel(), [-1e4, 1.15e-4, 12, -0.1]):
    ax.plot(x, y+y0, 'b-')
    ax.yaxis.set_major_formatter(PowerMultipleOfThreeFormatter())

fig.tight_layout()
plt.show()

В общем, идея состоит в том, чтобы вычислить показатель степени и мантиссу числа и манипулировать двумя так, чтобы показатель степени был кратным 3 (с (exponent//3)*3 иexponent%3).Для множителя уже было продемонстрировано здесь , где и как эти вычисления должны быть добавлены (то есть в _set_orderOfMagnitude).Значение смещения сохраняется в ScalarFormatter.offset, а строковое представление вычисляется в функции format_data().Перегрузив эту функцию, мы можем изменить отображение смещения.Код также содержит пример того, как использовать новый форматер (способ генерации данных снова бесстыдно копируется из здесь ).Результат кода выглядит следующим образом:

result of above code

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