我有一些数据被绘制,我强制科学记数法为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标签旁边,如下图所示?
答案 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()
答案 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_())