带有对数刻度 x 轴的条形图的自定义科学轴单位 [英] Custom scientific axis unit for a bar plot with log scale x-axis

查看:73
本文介绍了带有对数刻度 x 轴的条形图的自定义科学轴单位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Let's consider the following example to plot some y values for given x values.

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).

My goal is to have equally-spaced x-ticks for all x values (i.e., not linearly scaled). Moreover, I'd like to see the values in scientific notation (i.e., 1e9).

test1.png 完全没有显示任何有意义的内容.

test1.png does not show anything meaningful at all.

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

test2.png shows the values in the desired way, but does not have the scientific label on the bottom right (1e9).

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

How can I either place 1e9 manually in the x-axis unit location or work around my issue?

推荐答案

您的第一个图不显示条形,因为默认宽度 0.8 使它们与 x 轴上的数据范围相比非常细.你需要让它们更宽.

Your first plot doesn't show the bars as the default width of 0.8 makes them extremely thin compared to the data range on the x-axis. You need to make them much wider.

对数刻度将使位置等距.要根据需要显示刻度,可以明确设置它们,默认的 ScalarFormatter 可以替换 plt.xscale('log') 附带的 LogFormatter代码>.默认位置仍然会有小刻度(例如对数刻度中的 3,5,6,7),可以使用 NullLocator 来抑制.

A logscale will make the positions equidistant. To show the ticks as desired, they can be set explicitly and the default ScalarFormatter can replace the LogFormatter that comes with plt.xscale('log'). There still will be minor ticks at the default positions (e.g. 3,5,6,7 in logscale), which can be suppressed with a NullLocator.

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

To obtain nicely centered bars, the default centering doesn't work well with the log scale. Exact positions and widths can be calculated in log space and then transformed again to the linear space. The example below takes the shortest x-distance and multiplies it with 0.8 for separation.

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()

这篇关于带有对数刻度 x 轴的条形图的自定义科学轴单位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆