在条形图 matplotlib 中设置两个轴对数

Setting both axes logarithmic in bar plot matploblib

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

如果我设置 plt.bar(x, y, width=10, color='b', log=True),这允许我将 y 轴设置为对数,但我无法设置 x 轴对数。 我试过 plt.xscale('log') 不幸的是,这不起作用。 x 轴刻度消失,条形的宽度不相等。

如有任何帮助,我将不胜感激。

默认情况下,bar绘图的条形宽度为 0.8。因此,在对数刻度上,对于较小的 x 值,它们显得较大。如果不指定恒定宽度,而是使用 bin 边缘之间的距离并将其提供给 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。

如果目标是等宽条,假设数据点不等距,那么最合适的解决方案是将宽度设置为 plt.bar(x, y, width=c*np.array(x), color='b', log=True) 用于适合情节的常量 c。对齐可以是任何东西。

我知道这是一个非常古老的问题,你可能已经解决了,但我来到这个 post 因为我遇到了类似的问题,但在 y 轴上,我设法解决了它使用 ax.set_ylim(df['my data'].min()+100, df['my data'].max()+100)。在 y 轴上,我有一些合理的信息,我认为最好的方法是以对数刻度显示,但是当我设置对数刻度时,我看不到正确的数字(因为 x 轴上的 post)所以我就离开了使用日志并使用最小和最大参数的想法。它设置我的图表的比例很像日志。仍在寻找另一种不需要在 set_ylim.

处使用 -+100 的方法

虽然这实际上并没有使用 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.

Resulting plot - no frills

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