首页 > 解决方案 > 如何在matplotlib中将刻度设置为2的幂?

问题描述

我想绘制一个 xtick 值以 2 次方增长的图形。

例如,

import pandas as pd
data = pd.DataFrame({
    'x': [2, 4, 8, 16, 32, 64],
    'y': [1, 2, 3, 4, 5, 6]
})

我期待的是这样的人物, 在此处输入图像描述

对于像上面示例这样整齐的数据,我可以x2在这个数据框中创建一个 1~6 的辅助列,然后将图形的 xticklabels 设置为 2^1~2^6。但是,此解决方法不适用于具有其他值(如 3、7 或 30)的情况。

似乎 matplotlib 只支持对数刻度。如何以 2 的功率刻度实现刻度?

标签: pythonpandasdataframematplotlib

解决方案


这是一个特别棘手的问题(我没想到会是^^)。

好的,让我们从一些阅读提示开始:您想要设置 x/y 比例:.matplotlib.axes.Axes.set_yscale()。虽然有几个标准比例(默认显然是'liner',但可以设置自定义比例。这里有一些很好的例子。

基本上,您定义了两个具有正向变换和逆向变换的函数。之后,您需要正确设置刻度(因为您在绘图应用了转换,刻度保持不变(但由于转换而不在同一位置)。对此有两种选择:

  • 手动设置刻度matplotlib.axes.Axes.set_xticks(),或
  • 通过设置轴的定位器matplotlib.axes.Axes.xaxis.set_major_locator(): 。如果您使用网格,建议您这样做。但是由于我的知识有限,我很感激更详细的解释(因为现在我也很好奇这个功能^^)

现在是棘手的部分:格式化刻度标签以表示'2^x'. 没有比将它们明确设置为字符串更好的主意了。似乎人们只能在有限的范围内更改一般格式,请参阅matplotlib.pyplot.ticklabel_format(),在哪里可以选择是否以及何时应该使用科学记数法(即'10^x'在右下角显示 a)。让我知道是否有更通用的解决方案。

import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.ticker import FixedLocator

# create dummy data
df = pd.DataFrame({
    'x': [2**x for x in range(1,10)],
    'y': list(range(1,10))
})

def forward(x):
    return np.log2(x)


def inverse(x):
    return 2**x

# open figure
fig, ax = plt.subplots(2,2)
axs = ax.flatten()
for i in range(0,4):
    # plot data
    axs[i].plot(df['x'],df['y'])
    if i > 0:
        # set scale function
        axs[i].set_xscale('function', functions=(forward,inverse))
    if i > 1:
        # set ticks
        # - OPTION 1
        axs[i].set_xticks(df['x'])
        # - OPTION 2
      axs[i].xaxis.set_major_locator(FixedLocator(2**np.arange(1,10)))
    if i > 2:
        # est tick labels
        axs[i].set_xticklabels( [f"2^{j:.0f}" for j in np.log2(df['x'])] )

plt.show()

推荐阅读