如何将y轴比例因子移动到y轴标签旁边的位置?

时间:2017-08-18 16:02:39

标签: python matplotlib

我有一些数据被绘制,我强制科学记数法为10的幂(而不是指数)。下面是一段代码:

import matplotlib.ticker as mticker

formatter = mticker.ScalarFormatter(useMathText=True)
formatter.set_powerlimits((-3,2))
ax.yaxis.set_major_formatter(formatter)

但是, x10 ^ -4 的比例因子出现在图表的左上角。

是否有一种简单的方法可以强制将此比例因子的位置放在y标签旁边,如下图所示?

enter image description here

2 个答案:

答案 0 :(得分:6)

您可以将偏移设置为不可见,这样它就不会出现在原始位置。

ax.yaxis.offsetText.set_visible(False)

然后,您可以从格式化程序获取偏移量并使用它更新标签

offset = ax.yaxis.get_major_formatter().get_offset()
ax.yaxis.set_label_text("original label" + " " + offset)

使其出现在标签内。

以下内容使用带回调的类自动执行此操作,这样如果偏移更改,它将在标签中更新。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mticker

class Labeloffset():
    def __init__(self,  ax, label="", axis="y"):
        self.axis = {"y":ax.yaxis, "x":ax.xaxis}[axis]
        self.label=label
        ax.callbacks.connect(axis+'lim_changed', self.update)
        ax.figure.canvas.draw()
        self.update(None)

    def update(self, lim):
        fmt = self.axis.get_major_formatter()
        self.axis.offsetText.set_visible(False)
        self.axis.set_label_text(self.label + " "+ fmt.get_offset() )


x = np.arange(5)
y = np.exp(x)*1e-6

fig, ax = plt.subplots()
ax.plot(x,y, marker="d")

formatter = mticker.ScalarFormatter(useMathText=True)
formatter.set_powerlimits((-3,2))
ax.yaxis.set_major_formatter(formatter)

lo = Labeloffset(ax, label="my label", axis="y")


plt.show()

enter image description here

答案 1 :(得分:0)

GUI的最小示例,其中draw()应仅在每次绘图刷新时调用一次。保持正确的比例因子。也可以与锁定指数一起使用,例如比如here

作为一个例子,我只是添加了一个简单的按钮来刷新情节,但它也可以是任何其他事件。

from PyQt5.Qt import *
from PyQt5 import QtWidgets, QtCore # sorry about the Qt Creator mess
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
from matplotlib.ticker import ScalarFormatter
import numpy as np


class WidgetPlot(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)
        self.setLayout(QVBoxLayout())
        self.canvas = PlotCanvas(self)
        self.layout().addWidget(self.canvas)

class PlotCanvas(FigureCanvas):
    def __init__(self, parent = None, width = 5, height = 5, dpi = 100):
        self.fig = Figure(figsize = (width, height), dpi = dpi, tight_layout = True)
        self.ax = self.fig.add_subplot(111)

        FigureCanvas.__init__(self, self.fig)

    def majorFormatterInLabel(self, ax, axis, axis_label, major_formatter):
        if axis == "x":
            axis = ax.xaxis
        if axis == "y":
            axis = ax.yaxis

        axis.set_major_formatter(major_formatter)
        axis.offsetText.set_visible(False)
        exponent = axis.get_offset_text().get_text()
        axis.set_label_text(axis_label + " (" + exponent + ")")


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(674, 371)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(50, 10, 601, 281))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        self.mpl_layoutBox = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.mpl_layoutBox.setContentsMargins(0, 0, 0, 0)
        self.mpl_layoutBox.setObjectName("mpl_layoutBox")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(280, 300, 113, 32))
        self.pushButton.setObjectName("pushButton")
        MainWindow.setCentralWidget(self.centralwidget)

        self.w = WidgetPlot()
        self.canvas = self.w.canvas
        self.mpl_layoutBox.addWidget(self.w)

        self.pushButton.clicked.connect(self.refresh)



    def refresh(self):
        self.canvas.ax.clear()

        # Could've made it more beautiful. In any case, the cost of doing this is sub-ms.
        formatter = ScalarFormatter()
        formatter.set_powerlimits((-1, 1))
        self.canvas.majorFormatterInLabel(self.canvas.ax, "y", "label", major_formatter = formatter)

        r = np.random.choice((1e3, 1e5, 1e7, 1e9, 1e100))
        self.canvas.ax.plot(r)
        self.canvas.draw()


if __name__ == "__main__":
    import sys
    app = QApplication(sys.argv)
    TraceWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(TraceWindow)
    TraceWindow.show()
    sys.exit(app.exec_())