具有对数刻度x轴的条形图的自定义科学轴单位

时间:2020-10-11 09:40:41

标签: python matplotlib

让我们考虑以下示例,为给定的y值绘制一些x值。

import matplotlib.pyplot as pyplot

if __name__ == "__main__":
  x = [1000000000, 2000000000, 4000000000, 8000000000]
  y = [0.342, 0.543, 0.874, 1.324]
  
  pyplot.bar(x, y)
  pyplot.savefig("test1.png", format="png")
  pyplot.close()

  pyplot.bar([str(int(x_value / 1000000000)) for x_value in x], y)
  pyplot.savefig("test2.png", format="png")
  pyplot.close()

我的目标是为所有x值设置等距的x刻度(即,不是线性缩放)。此外,我希望以科学计数法(即1e9)看到这些值。

test1.png根本没有显示任何有意义的内容。

enter image description here

test2.png以所需的方式显示值,但右下角(1e9)没有科学标签。

enter image description here

我如何手动将1e9放在x轴单位位置或解决我的问题?

1 个答案:

答案 0 :(得分:1)

您的第一张图没有显示这些条形图,因为默认宽度0.8使其与x轴上的数据范围相比非常细。您需要使它们更宽。

对数刻度将使位置等距。要根据需要显示刻度,可以显式设置刻度,默认的ScalarFormatter可以替换LogFormatter随附的plt.xscale('log')。在默认位置(例如,对数刻度上的3,5,6,7)仍会出现较小的滴答声,可以用NullLocator来消除。

要获得精确居中的条形图,默认居中不适用于对数刻度。可以在对数空间中计算出精确的位置和宽度,然后将其再次转换为线性空间。下面的示例采用最短的x距离,并将其乘以0.8进行分离。

import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter, NullLocator
import numpy as np

x = np.array([1000000000, 2000000000, 4000000000, 8000000000])
y = [0.342, 0.543, 0.874, 1.324]

log_x = np.log(x)
log_width = 0.8 * np.diff(np.log(x)).min()
lefts = np.exp(log_x - log_width / 2)
rights = np.exp(log_x + log_width / 2)

ax = plt.gca()
ax.bar(lefts, y, width=[xi * 0.6 for xi in x], align='edge')
ax.set_xscale('log')
ax.set_xticks(x)
ax.xaxis.set_major_formatter(ScalarFormatter())
ax.xaxis.set_minor_locator(NullLocator())  # optionally remove the minor ticks
plt.tight_layout()
plt.show()

resulting plot