В основном я хочу, чтобы вместо построения и смещения 10 ^ 8 10 ^ 5 или 1e8 1e5 и т. д. они были в стандартных единицах, таких как 10 ^ 3 10 ^ 6 1e3 1e6 и т. д.
Это возможно? и если да то как?
заранее спасибо
В основном я хочу, чтобы вместо построения и смещения 10 ^ 8 10 ^ 5 или 1e8 1e5 и т. д. они были в стандартных единицах, таких как 10 ^ 3 10 ^ 6 1e3 1e6 и т. д.
Это возможно? и если да то как?
заранее спасибо
plt.gca().get_xaxis().get_major_formatter().set_useOffset(False)
Вы имеете в виду это? (то же самое касается оси Y). Это возможный дубликат этого вопроса, в котором второй ответ дает более каноническое описание, чем я. Проголосуйте за него, если это то, что вы ищете.
ИЗМЕНИТЬ
Я играл с этим в течение всего дня, и кажется, что настройка ax.yaxis.set_scientific(True)
автоматически превосходит любую ax.yaxis.setOffset = False
. Неважно, каким образом вы это сделаете. Я не мог обойти это, и тогда я усугубился.
Вот обходной путь, протестирован Py3.4, mpl 1-3-1 win7.
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from decimal import Decimal
x_large = np.arange(10, 20000, 100)
y_large = np.arange(10, 20000, 100)
x_small = np.arange(-1, 1, 0.000001)
y_small = np.arange(-1, 1, 0.000001)
metric = [0,1,2,3,6,9, 12, 16]
def format_large(x):
x = float(x)
sx = str(x)
sx = sx.split(".")[0]
if len(sx)-1 in metric:
return "%se%s" % (sx[0], len(sx)-1)
add = - max(exp-len(sx)-1 for exp in metric if exp<len(sx)-1)
return "%se%s" % (sx[0:add], len(sx)-add)
#love thy DRY principle
def check_metric_small(num, exp):
if exp in metric:
return "%se-%s" % (num[0], exp)
add = min(mexp-exp for mexp in metric if mexp>exp)
num = num.ljust(add+1, "0")
return "%se-%s" % (num[0:add+1], exp+add)
def format_small(x):
sx = str(x)
#string representation of numbers after e-4 is
#done in scientific manner 1e-5, 1e-6 ...
if sx.find("e") != -1:
num, exp = sx.split("e")
exp = -int(exp)
return check_metric_small(num, exp)
#numbers up to e-4 are represented in string form
#as is, therefore 0.1, 0.01
s = sx.split(".")[-1]
num = s.strip("0")
exp = len(s)-len(num)
return check_metric_small(num, exp+1)
def formatter(x, p):
if x<0: #make sure we don't send a negative number
res = "-" #rather just tack on the minus sign
x = -x
else: res = ""
if abs(x)<1 and x!=0.0:
return res+format_small(x)
return res+format_large(x)
fig, ax = plt.subplots()
y_formatter = mpl.ticker.FuncFormatter(formatter)
ax.yaxis.set_major_formatter(y_formatter)
ax.plot(x_large,y_large)
plt.show()
Где важные функции содержатся в format_large
и format_small
. Они будут округлять числа до ближайшего меньшего показателя степени, определяемого списком metric
. Сами по себе они не могут обрабатывать отрицательные числа, поэтому используйте функцию formatter
.
Переключение между большим увеличением и уменьшением масштаба, кажется, не оставляет после себя никаких странных эффектов, равно как и переход через ноль. Ниже приведена суть этих функций:
for i in [0, 10, 50, ......]:
print(format_large(i), float(format_large(i)) == i)
0e0 True 5e6 True
1e1 True 5e6 True
5e1 True 50e6 True
5e2 True 500e6 True
5e3 True 50e9 True
50e3 True 500e9 True
500e3 True 5e12 True
for i in [0.05, 0.005, ......]:
print(format_small(i), float(format_small(i)) == i)
5e-2 True 50e-9 True
5e-3 True 5e-9 True
500e-6 True 500e-12 True
50e-6 True 50e-12 True
5e-6 True 50e-12 True
500e-9 True 5000e-16 True
Будьте осторожны, потому что я округляю числа, вы можете тестировать только с округленными числами.
Что происходит с большими числами, так это то, что я беру их строковое представление, то есть "500.0"
. Длина числа, вычтенного из единицы, дает мне количество нулей\порядок числа. Если это метрический порядок, я возвращаю простейшую строку, содержащую только первую цифру числа и его показатель степени.
Если порядок числа не метрический, я нахожу первый меньший метрический показатель: max(exp-len(sx) for exp in metric if exp<len(sx))
(это означает, найдите мне наибольшую разницу между показателем метрической системы и моим текущим числовым порядком для всех метрических показателей, которые ниже текущего порядок номеров). Это гарантирует, что все различия будут отрицательными, а наибольшее число всегда будет указывать на ближайший показатель степени. Возвращаемая строка, в которой «основное» число имеет более 1 цифры, насколько больше определяется разницей между ближайшим показателем степени и текущим порядком чисел.
Маленькие числа становятся действительно сложными, потому что нужно рассмотреть 2 случая. Когда число больше 0.0004
, его представление не изменится. Однако для чисел, меньших этого, их представление изменится на научное.
Я разделил научное представление на букву «е», чтобы получить фактическое число, то есть 1234
, и показатель степени. Если показатель степени относится к метрической системе, вернуть строку. В противном случае получите следующий меньший индекс метрики и дополните число, пока оно не будет соответствовать: mexp-exp for mexp in metric if mexp>exp
(это означает: для всех показателей степени, которые больше, чем текущий порядок чисел, и помните, что я изменил текущий порядок на положительное число, поэтому больший показатель степени коррелирует с меньшим фактическое число, найдите мне минимальную разницу текущего и метрического показателей). Прежде чем вернуть строку, я дополняю правую часть своего числа достаточным количеством нулей с помощью ljust
, чтобы не рисковать поднять индекс за пределы ошибки.
Для небольших чисел, не представленных с научной точки зрения, то есть 0.000432
, я разделяю их на .
, удаляю начальные нули, чтобы получить только число 432
. Длина того, что вычитается из длины всего разделенного числа 000432
, определяет, сколько у меня нулей. Оттуда я повторяю процедуру поиска следующего ближайшего метрического показателя или немедленно возвращаю строку.
Функции не имеют параметра количества десятичных знаков, но добавить его должно быть тривиально. Оператор if
перед возвратом результата и изменением операторов возврата на что-то вроде "%s%se%s" % (sx[0:add], sx[add:ndecimals], len(sx)-add)
должен решить эту проблему.
Я хотел бы сказать, что это было весело. Но это было не так :D я очень долго копался в руководстве, пока не сдался. Но я сказал, что вернусь к вам, так что вот.
set_scientific
, который вы можете использовать изScalarFormater
, но я пока не могу заставить его работать. Я отредактирую через минуту или две 02.03.2015