Python 如何在绘图中创建自定义(非线性,非对数)x轴

Python 如何在绘图中创建自定义(非线性,非对数)x轴,python,matplotlib,Python,Matplotlib,我使用matplotlib绘制一系列数据,如下所示,这些数据在x轴上分布非常不均匀(单位:秒)。 比如,这里,图1,在0-100秒之间非常浓缩,之后就不那么浓缩了。但在线性x轴上,我们无法清楚地看出浓缩的事实。 因此,我想自定义x轴以放大某些部分并缩小其他部分。例如,在这里,放大0-100秒(可能占据几乎一半的轴),缩小100-1750秒(另一半轴) 下图2是我所说的“定制”x轴的一个示例,它的轴上有[0.5s、1.3s、5s、10s、20s、30s、60s、2m、5m、10m、8h] 很抱

我使用matplotlib绘制一系列数据,如下所示,这些数据在x轴上分布非常不均匀(单位:秒)。 比如,这里,图1,在0-100秒之间非常浓缩,之后就不那么浓缩了。但在线性x轴上,我们无法清楚地看出浓缩的事实。 因此,我想自定义x轴以放大某些部分并缩小其他部分。例如,在这里,放大0-100秒(可能占据几乎一半的轴),缩小100-1750秒(另一半轴)

下图2是我所说的“定制”x轴的一个示例,它的轴上有[0.5s、1.3s、5s、10s、20s、30s、60s、2m、5m、10m、8h]


很抱歉,我是新来的,无法将数字直接附加到聊天室。

不同“缩放”级别的不同部分

您描述希望您的体形在0到100之间放大,在100到1750之间缩小。为此,您可以创建类似于“断轴”示例的内容,但让我向您展示如何将其应用于数据集

首先,让我生成一个类似于您的假数据集,因为您没有提供数据集

large_peak = 10 * np.random.randn(100) + 10
other_data = 2000 * np.random.uniform(size=10)
data = np.concatenate((large_peak, other_data))

fig, ax = plt.subplots()

bins = np.arange(0, np.max(data), 20)
ax.hist(data, bins=bins, density=True)
这将产生下图:

现在,为了创建轴断裂的图形,我们将图形拆分为两个子图,在这些子图中绘制相同的数据,隐藏子图之间的线,使子图连接,并正确设置其x限制

# sharey to have the same y axis limits, wspace=0 to make the axes connect
fig, (ax1, ax2) = plt.subplots(1, 2, sharey=True, gridspec_kw={'wspace': 0})

# x limits of the axes
xlim1 = (0, 100)
xlim2 = (100, 1750)

# calculate the histogram bin width such that it is equal for both axes
# we choose 50 bins per axis, you can change this value
bins1 = np.arange(xlim1[0], xlim1[1] + 1, np.diff(xlim1) / 50)
bins2 = np.arange(xlim2[0], xlim2[1] + 1, np.diff(xlim2) / 50)

# plot the same data in both axes
ax1.hist(data, bins=bins1, density=True)
ax2.hist(data, bins=bins2, density=True)

# hide the spines and ticks
ax1.spines.right.set_visible(False)
ax2.spines.left.set_visible(False)
ax2.tick_params(axis='y', left=False)

# set the x limits
ax1.set_xlim(xlim1)
ax2.set_xlim(xlim2)
这将产生下图:

现在,您可以看到图形的左半部分被放大,而右半部分被缩小。您可能希望澄清轴的这种变化,例如使用穿过中间的灰色虚线

# add line to indicate the change in x scale
ax1.axvline(xlim1[1], clip_on=False, color='gray', linestyle=':')

对数刻度?

您问题的标题表明您不想对图形使用对数刻度,您给出了一个具有不同x轴的图形示例(您称之为“figure2”)。然而,这个图形的x轴有一个对数刻度,其刻度刚刚被非常规地放置(以指示数据中的峰值)。请参见下图,其中我使用了“60”刻度(1分钟)和“10米”刻度(10分钟)之间的差值来计算x轴上的十年大小:


很明显,您可以看到此图中的x轴实际上是按对数缩放的。您可以使用该方法将刻度放置在不同的位置,也可以放置在对数比例的图形中。

下面是创建第二个示例的方法,该示例使用对数比例。可以创建一个显示x记号的值,以显示秒、分钟或小时

导入matplotlib.pyplot作为plt
从matplotlib.ticker导入NullFormatter、FuncFormatter
将numpy作为np导入
分钟=60
小时=60*分钟
def hms_格式化程序(x,pos):
如果x<120:
返回f'{x:g}'
elif x<120*分钟:
返回f'{x/分钟:g}m'
其他:
返回f'{x/小时:g}h'
图,ax=plt.子批次()
ax.setxscale('log'))
ax.set_xticks([.5,1.3,5,10,20,30,60,2*分钟,5*分钟,10*分钟,8*小时])
ax.set_xticks([i代表范围(1,20)中的i)]+[i代表范围(20,120,10)中的i]
+[i*分钟表示i在范围(1,20)]+[i*分钟表示i在范围(20,120,10)]
+[i*i在(1,10)范围内的小时数],
次要=正确)
ax.xaxis.set\u major\u格式化程序(FuncFormatter(hms\u格式化程序))
ax.xaxis.set_minor_格式化程序(NullFormatter())
x=np.logspace(0,np.log10(8*h),200)
y=np.随机.正常(0.1,1200).cumsum()+5
轴图(x,y)
最大利润率(x=0)
ax.set_ylim(ymin=0)
plt.show()

谢谢您的回答,但我返回了以下内容,您的回答中没有提到任何内容?-------------------------------------------------------------TypeError:格式化程序参数应为matplotlib.ticker.formatter的实例。我编辑了代码以使用FuncFormatter使其也适用于较旧的matplotlib版本。(如果可能的话,强烈建议您升级。)感谢JohanC,我发现了一个有趣的问题,通过这种方式(x=np.logspace(0,np.log10(8*hours),x轴的起点将始终是1,不能达到0。我尝试使用float('-inf')而不是0,但出现了一个错误。我发布的图片是如何达到0的?我想他们没有达到0,只是0和1之间的某个点,用对数刻度,0将处于负无穷大,所以不可能显示。此外,在绘图上放一个非常小的数字(比如说
1e-10
)会使所有内容都拉伸得太多。要在这样一个轴上置零,有一个
半对数
标度,它以线性标度将零件拉近零。Matplotlib还有一个
symlog
刻度,它通过绝对值的对数绘制负值,并使用零附近的半对数。非常感谢你,有了你,我终于发现我想要的实际上是一个缩放的对数数字…:-)真的很感激!