在Matplotlib中绘制条形图时,设置两个轴为对数轴。

9

我已经分组数据以绘制直方图。因此,我正在使用plt.bar()函数。我想将绘图中的两个轴设置为对数刻度。

如果我设置plt.bar(x, y, width=10, color='b', log=True),这样可以将y轴设置为对数,但我不能设置x轴的对数刻度。 我曾尝试过plt.xscale('log'),但很遗憾,它不能正常工作。 x轴刻度会消失,而条形图的宽度也不相等。

enter image description here

如果有人能提供帮助,我将不胜感激。

4个回答

12

默认情况下,bar图的条形宽度为0.8。因此,在对数比例尺上,较小的x值会使它们看起来更大。如果不是指定一个固定宽度,而是使用直方图边缘之间的距离并将其提供给width参数,则条形图将具有正确的宽度。同时需要将align设置为"edge"才能正常工作。

import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)

x = np.logspace(0, 5, num=21)
y = (np.sin(1.e-2*(x[:-1]-20))+3)**10

fig, ax = plt.subplots()
ax.bar(x[:-1], y, width=np.diff(x), log=True,ec="k", align="edge")
ax.set_xscale("log")
plt.show()

输入图像描述

我无法在对数刻度下复制缺失的刻度标签。这可能是由于代码中未在问题中显示的某些设置,或由于使用了旧版matplotlib。此示例在matplotlib 2.0中正常工作。


1
我该如何在density=True的情况下使用它? - ManuelSchneid3r
这对我有用。不过,我要补充的一点是解决方案通过使用 x[:-1] 来作为X数据来避免了一个问题,但实际数据集可能并不现实。为了纠正这个问题,你可以简单地重复最后一个bin的宽度。我创建了一个变量,并传递给width参数:bin_widths = np.pad(np.diff(my_x_data), (0,1), mode="edge") - astroChance

3

如果目标是拥有等宽的条形图,假设数据点不是等距的,则最合适的解决方案是将宽度设置为plt.bar(x, y, width=c*np.array(x), color='b', log=True),其中c是适合绘图的常数。对齐方式可以是任何东西。


0

我知道这是一个非常老的问题,你可能已经解决了,但我来到这篇文章是因为我遇到了类似于y轴的问题,我成功地使用ax.set_ylim(df['my data'].min()+100, df['my data'].max()+100)解决了它。在y轴上,我有一些敏感信息,我认为最好的方法是以对数比例显示,但当我设置对数比例时,我无法正确地看到数字(就像这篇文章中的x轴),所以我放弃了使用对数的想法,使用了最小和最大参数。它设置了我的图形尺度,就像对数一样。仍在寻找另一种不需要使用-set_ylim中的-+100的方法。


0

虽然这并没有实际使用pyplot.bar,我认为这种方法可能对于实现OP试图完成的操作有所帮助。我发现这比尝试根据对数比例刻度来校准宽度要容易,尽管需要更多步骤。创建一个线集合,其宽度独立于图表比例。

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.collections as coll
#Generate data and sort into bins
a = np.random.logseries(0.5, 1000)
hist, bin_edges = np.histogram(a, bins=20, density=False)

x = bin_edges[:-1] # remove the top-end from bin_edges to match dimensions of hist

lines = []
for i in range(len(x)):
    pair=[(x[i],0), (x[i], hist[i])]
    lines.append(pair)

linecoll = coll.LineCollection(lines, linewidths=10, linestyles='solid')
fig, ax = plt.subplots()
ax.add_collection(linecoll)
ax.set_xscale("log")
ax.set_yscale("log")
ax.set_xlim(min(x)/10,max(x)*10)
ax.set_ylim(0.1,1.1*max(hist)) #since this is an unweighted histogram, the logy doesn't make much sense.

结果图-简洁版

一个缺点是“条形”将会居中,但这可以通过将x值偏移半个线宽值来改变...我认为应该是
x_new = x + (linewidth/2)*10**round(np.log10(x),0)。


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