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

2024-04-19 05:17:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我画了一些数据,我把它们用科学的方法画成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


Tags: 数据方法代码importmatplotlibformatteras科学
2条回答

可以将偏移设置为“不可见”,使其不显示在其原始位置。在

ax.yaxis.offsetText.set_visible(False)

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

^{pr2}$

使其出现在标签内。在

下面的代码使用一个带有回调的类来自动执行此操作,这样如果偏移量更改,它将在标签中更新。在

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

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_())

相关问题 更多 >