Как можно гиперболически масштабировать оси Matplotlib?
У меня есть сюжет примерно такой:
Различия между двумя линиями (красной и синей) наиболее важны в моих фактических данных (кривая ROC), скажем, в ячейке сетки. 0.2<x<0.4
, 0.8<y<1
. Теперь я мог бы обрезать эту ячейку сетки, но, скажем, я бы предпочел гиперболически масштабировать оси x и y - где гиперболическая кривая оси Y имеет пик примерно на отметке 0,9, а ось x имеет пик примерно на отметке 0.3 - таким образом, что двумерное пространство растягивается для интересующей ячейки сетки и уплотняется в другом месте (с сохранением значения отметок на осях). Как этого добиться? Начало моей попытки ниже. Как мой код будет изменен для реализации описанного мной масштабирования оси?
from matplotlib import gridspec
from matplotlib import scale as mscale
from matplotlib import transforms as mtransforms
from matplotlib.ticker import FormatStrFormatter
from matplotlib.ticker import NullFormatter, NullLocator, MultipleLocator
import math
import matplotlib
import matplotlib.patches as mpatches
import matplotlib.pylab as plt
import matplotlib.pyplot as plt
import matplotlib.ticker
import numpy as np
import seaborn as sns
sns.set_palette('husl')
sns.set()
plt.rcParams["figure.figsize"] = [5, 5]
x = np.arange(0, 1, step=0.01)
y1 = 1-1/np.exp(10*x)
y2 = 1-1.1/np.exp(10*x)
plt.scatter(x, y1, s=1, facecolor='red')
plt.scatter(x, y2, s=1, facecolor='blue')
plt.show();
class CustomScale(mscale.ScaleBase):
name = 'custom'
def __init__(self, axis, **kwargs):
mscale.ScaleBase.__init__(self)
self.thresh = None #thresh
self.name = 'custom'
def get_transform(self):
return self.CustomTransform(self.thresh)
def set_default_locators_and_formatters(self, axis):
pass
class CustomTransform(mtransforms.Transform):
input_dims = 1
output_dims = 1
is_separable = True
def __init__(self, thresh):
mtransforms.Transform.__init__(self)
self.thresh = thresh
def transform_non_affine(self, a):
#return np.log(1+a)
return np.exp(a)-1
#return 1+(1/2)*a
mscale.register_scale(CustomScale)
plt.scatter(x, y1, s=1, facecolor='red')
plt.scatter(x, y2, s=1, facecolor='blue')
plt.xscale('custom')
plt.show();
1 ответ
Вы можете достичь этого, используя
FuncScale
(зарегистрировано как
'function'
).
f = lambda a: np.exp(a) - 1
g = lambda b: np.log(b + 1)
plt.xscale('function', functions=(f, g))
Для гиперболического масштабирования вы можете использовать
lambda x: 1 / x
для обеих функций.
См. пример в документации весов: https://matplotlib.org/3.3.4/gallery/scales/scales.html .