matplotlib에서 눈금 눈금을 2의 거듭 제곱으로 설정하는 방법은 무엇입니까? [복제]

Dec 16 2020

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의 거듭 제곱 척도로 진드기를 어떻게 얻을 수 있습니까?

답변

max Dec 16 2020 at 17:20

이것은 특히 트릭 질문입니다 (내가 기대하지 않았던 ^^).

자, 읽기를위한 몇 가지 힌트부터 시작하겠습니다. 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'오른쪽 하단에 표시 ). 이에 대한보다 일반적인 솔루션이 있는지 알려주십시오.

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