在matplotlib中按比例更改绘图比例

43

我在使用Python创建一个图表。是否有一种方法可以通过缩放因子重新调整坐标轴?yscalexscale命令只能让我关闭对数刻度。

编辑:
例如,如果我的绘图中x轴范围从1纳米到50纳米,则x轴范围将从1x10^(-9)到50x10^(-9),我想要它改变为1到50。因此,我希望绘图函数将绘制在图表上的x值除以10^(-9)。


7
Yotam,你似乎有许多未解决的问题已经得到了回答,但你还没有接受任何一个答案。请接受这些老问题的回答或者提供额外的信息,这样我们才能帮助你! - Hooked
3个回答

93

正如您已经注意到的那样,xscaleyscale不支持简单的线性重新缩放(不幸的是)。除了Hooked的答案之外,您可以通过以下方式来欺骗标签而不会干扰数据:

ticks = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x*scale))
ax.xaxis.set_major_formatter(ticks)

一个完整的示例,展示了x和y的缩放:

import numpy as np
import pylab as plt
import matplotlib.ticker as ticker

# Generate data
x = np.linspace(0, 1e-9)
y = 1e3*np.sin(2*np.pi*x/1e-9) # one period, 1k amplitude

# setup figures
fig = plt.figure()
ax1 = fig.add_subplot(121)
ax2 = fig.add_subplot(122)
# plot two identical plots
ax1.plot(x, y)
ax2.plot(x, y)

# Change only ax2
scale_x = 1e-9
scale_y = 1e3
ticks_x = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x/scale_x))
ax2.xaxis.set_major_formatter(ticks_x)

ticks_y = ticker.FuncFormatter(lambda x, pos: '{0:g}'.format(x/scale_y))
ax2.yaxis.set_major_formatter(ticks_y)

ax1.set_xlabel("meters")
ax1.set_ylabel('volt')
ax2.set_xlabel("nanometers")
ax2.set_ylabel('kilovolt')

plt.show() 

最后我有一张图片的制作积分:

左: ax1未缩放,右: ax2 y 轴缩放到千位,x 轴缩放到纳米

请注意,如果您像我一样使用了text.usetex: true,您可能需要用$括起标签,例如:'${0:g}$'


2
这可能是更正确的答案。谢谢@oystein - oche
那就是我们需要的黑客技巧。 - George Pligoropoulos
在左边你可以看到右下角的"x 10^-9"。使用FuncFormatter,这个特性似乎被禁用了。不幸的是,我需要这个特性。 - Sven
@Sven 关于您的问题,可以做的一件事是将因子“10^-9”移入轴标签,并让FuncFormatter函数也考虑它。 - Bastian

13

不要改变刻度,为什么不改变单位呢?创建一个单独的数组X来存储以nm为单位的x值。这样,当你绘制数据时,它已经处于正确的格式!只需确保添加xlabel来指示单位(无论如何都应该这样做)。

from pylab import *

# Generate random test data in your range
N = 200
epsilon = 10**(-9.0)
X = epsilon*(50*random(N) + 1)
Y = random(N)

# X2 now has the "units" of nanometers by scaling X
X2 = (1/epsilon) * X

subplot(121)
scatter(X,Y)
xlim(epsilon,50*epsilon)
xlabel("meters")

subplot(122)
scatter(X2,Y)
xlim(1, 50)
xlabel("nanometers")

show()

输入图像描述


2
这是我现在想做的事情。我认为还有更优雅的方式。 - Yotam

12

要设置x轴范围,可以使用set_xlim(left, right)方法,这里是文档

更新:

看起来你想要一个相同的图形,但只更改“刻度值”,你可以通过获取刻度值,然后将它们更改为所需的任何内容来实现。因此,对于您的需求,应该像这样:

ticks = your_plot.get_xticks()*10**9
your_plot.set_xticklabels(ticks)

据我理解,xlim改变绘图的范围而不是缩放它。请参考我的示例。 - Yotam
@Yotam - 所以您希望图表保持相同,但是x轴标签上的值会改变? - fraxel
2
惊人的简单解决方案。然而,我发现即使使用应该只显示整数的刻度线(例如MultipleLocator或MaxNLocator),标签仍带有小数。我发现可以通过使用“ticks.astype(int)”而不是“ticks”来解决这个问题。 - Mr.H
不幸的是,在绘图之前 get_xticks() 不起作用。这样做非常令人恼火和毫无意义。 - Aku

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接