matplotlib : 축 오프셋 값을 정수 또는 특정 숫자로 포맷


92

항상 나노초 (1e-9)라고하는 데이터를 플로팅하는 matplotlib 그림이 있습니다. y 축에 수십 나노초의 데이터가있는 경우, 즉. 44e-9에서 축의 값은 오프셋으로 + 1e-8을 사용하여 4.4로 표시됩니다. 어쨌든 + 1e-9 오프셋으로 축이 44를 표시하도록 강제하는 것이 있습니까?

축이 + 5.54478e4를 표시하는 x 축도 마찬가지입니다. 여기서는 +55447의 오프셋을 표시합니다 (정수, 소수 없음-여기 값은 일 단위).

나는 다음과 같은 몇 가지를 시도했습니다.

p = axes.plot(x,y)
p.ticklabel_format(style='plain')

x 축의 경우 작동하지 않지만 잘못 사용하거나 문서에서 무언가를 잘못 해석하고 있지만 누군가 올바른 방향으로 나를 가리킬 수 있습니까?

고마워요, 조나단

문제 그림


포맷터로 뭔가를 시도했지만 아직 해결책을 찾지 못했습니다 ... :

myyfmt = ScalarFormatter(useOffset=True)
myyfmt._set_offset(1e9)
axes.get_yaxis().set_major_formatter(myyfmt)

myxfmt = ScalarFormatter(useOffset=True)
myxfmt.set_portlimits((-9,5))
axes.get_xaxis().set_major_formatter(myxfmt)

참고로 '오프셋 번호'개체가 실제로 어디에 있는지 혼란스러워합니다 ... 메이저 / 마이너 틱의 일부입니까?


1
시도해 보셨습니까 set_units? matplotlib.sourceforge.net/api/… (여기에 matplotlib가 없기 때문에 시도 할 수 없습니다.)
Katriel

1
set_units 함수를 확인했는데 필요한 것보다 훨씬 복잡해 보입니다 (추가 모듈을 작성 / 추가해야합니까 ??-basic_units?). 진드기의 형식을 편집하는 방법이 있어야합니다. units / set_unit 함수는 단위 변환 라인을 따라 더 많이 보입니다. 팁을 주셔서 감사합니다. 지금 찾고있는 다른 솔루션을 소개했습니다!
Jonathan

1
rcParams기본적으로 끄면 끄는 것을 고려 rcParams["axes.formatter.useoffset"] = False하십시오 : 여기와 같이 : stackoverflow.com/questions/24171064/…
Ruggero Turra

답변:


100

나는 똑같은 문제가 있었고 다음 줄이 문제를 해결했습니다.

from matplotlib.ticker import ScalarFormatter

y_formatter = ScalarFormatter(useOffset=False)
ax.yaxis.set_major_formatter(y_formatter)

1
이것은 빠르고 쉬운 대답입니다. 감사합니다.
maxm

6
한 줄짜리는 다음과 같습니다.ax.get_yaxis().get_major_formatter().set_useOffset(False)
Dataman

3
나 같은 from matplotlib.ticker import ScalarFormatter멍청이를 위해 @Gonzalo의 코드가 작동하거나 단순히 위의
@Dataman

36

훨씬 쉬운 해결책은 단순히 눈금 레이블을 사용자 정의하는 것입니다. 이 예를 보자 :

from pylab import *

# Generate some random data...
x = linspace(55478, 55486, 100)
y = random(100) - 0.5
y = cumsum(y)
y -= y.min()
y *= 1e-8

# plot
plot(x,y)

# xticks
locs,labels = xticks()
xticks(locs, map(lambda x: "%g" % x, locs))

# ytikcs
locs,labels = yticks()
yticks(locs, map(lambda x: "%.1f" % x, locs*1e9))
ylabel('microseconds (1E-9)')

show()

대체 텍스트

y 축의 경우 값에 곱한 1e9다음 y 레이블에서 해당 상수를 언급 한 방법에 주목하십시오.


편집하다

또 다른 옵션은 플롯 상단에 텍스트를 수동으로 추가하여 지수 승수를 가짜로 만드는 것입니다.

locs,labels = yticks()
yticks(locs, map(lambda x: "%.1f" % x, locs*1e9))
text(0.0, 1.01, '1e-9', fontsize=10, transform = gca().transAxes)

EDIT2

또한 동일한 방식으로 x 축 오프셋 값의 형식을 지정할 수 있습니다.

locs,labels = xticks()
xticks(locs, map(lambda x: "%g" % x, locs-min(locs)))
text(0.92, -0.07, "+%g" % min(locs), fontsize=10, transform = gca().transAxes)

대체 텍스트


그게 처음에 제가 한 일입니다. 불행히도 축 승수를 설정 / 표시하는 쉬운 방법을 찾을 수 없었습니다 (명시 적으로 y 축 레이블에 넣는 것 외에는). 축 승수 레이블이 없어도 괜찮다면 이것이 더 간단한 방법입니다. 어느 쪽이든, 나에게서 +1.
Joe Kington

1
@Joe Kington : 수동으로 텍스트로 추가 할 수 있습니다 ... 위의 편집 내용 참조 :)
Amro

큰! x 축 레이블로 접근 방식을 시도해 보겠습니다. 첫 x 값의 하한값을 취한 다음 모든 x 값에서 제거하고 "+ minxval"을 레이블로 추가합니다. x-tick 오프셋을 포맷하는 다른 방법을 알아낼 수 없습니다. 오프셋의 크기는 괜찮습니다. 지수가 아닌 값으로 표시하기 만하면됩니다.
Jonathan

와. matplotlib를 실제로 제어하고 필요에 따라 조정하고 플롯을 실제로 약간 조정하는 방법을 보여주는 훌륭한 작업입니다.
physicsmichael

그림에서 1e-9의 글꼴 크기를 어떻게 변경합니까?
제안은 거부 할 수 없습니다

30

ScalarFormatter필요한 작업을 수행 하려면 하위 클래스를 만들어야 합니다 ... _set_offset상수를 추가하기 만하면 ScalarFormatter.orderOfMagnitude. 안타깝게도 수동 설정 orderOfMagnitude은 아무 작업도 수행하지 않습니다 ScalarFormatter. 축 눈금 레이블의 형식을 지정하기 위해 인스턴스가 호출 될 때 재설정되기 때문 입니다. 이렇게 복잡해서는 안되지만 원하는 작업을 정확하게 수행 할 수있는 더 쉬운 방법을 찾을 수 없습니다. 다음은 예입니다.

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

class FixedOrderFormatter(ScalarFormatter):
    """Formats axis ticks using scientific notation with a constant order of 
    magnitude"""
    def __init__(self, order_of_mag=0, useOffset=True, useMathText=False):
        self._order_of_mag = order_of_mag
        ScalarFormatter.__init__(self, useOffset=useOffset, 
                                 useMathText=useMathText)
    def _set_orderOfMagnitude(self, range):
        """Over-riding this to avoid having orderOfMagnitude reset elsewhere"""
        self.orderOfMagnitude = self._order_of_mag

# Generate some random data...
x = np.linspace(55478, 55486, 100) 
y = np.random.random(100) - 0.5
y = np.cumsum(y)
y -= y.min()
y *= 1e-8

# Plot the data...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, 'b-')

# Force the y-axis ticks to use 1e-9 as a base exponent 
ax.yaxis.set_major_formatter(FixedOrderFormatter(-9))

# Make the x-axis ticks formatted to 0 decimal places
ax.xaxis.set_major_formatter(FormatStrFormatter('%0.0f'))
plt.show()

다음과 같은 결과가 나타납니다. 대체 텍스트

반면 기본 형식은 다음과 같습니다. 대체 텍스트

도움이 되었기를 바랍니다.

편집 : 그만한 가치에 대해서는 오프셋 레이블이 어디에 있는지도 모르겠습니다 ... 수동으로 설정하는 것이 약간 더 쉬울 것입니다. 그러나 그렇게하는 방법을 알 수 없었습니다 ... 느낌이 들었습니다. 이 모든 것보다 더 쉬운 방법이 있어야합니다. 그래도 작동합니다!


감사! ScalarFormatter의 서브 클래 싱은 훌륭하게 작동합니다! 하지만 x 축에 대해 원하는 것을 명확하게 설명하지 않은 것 같습니다. x 축의 오프셋을 유지하고 싶지만 오프셋 값의 형식을 지정하여 지수로 표시되지 않도록합니다.
Jonathan

이것은 나를 위해 일한 유일한 방법입니다! 감사합니다 :)
Ocean Scientist

11

Amro의 답변과 유사하게 FuncFormatter를 사용할 수 있습니다.

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

# Generate some random data...
x = np.linspace(55478, 55486, 100) 
y = np.random.random(100) - 0.5
y = np.cumsum(y)
y -= y.min()
y *= 1e-8

# Plot the data...
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(x, y, 'b-')

# Force the y-axis ticks to use 1e-9 as a base exponent 
ax.yaxis.set_major_formatter(FuncFormatter(lambda x, pos: ('%.1f')%(x*1e9)))
ax.set_ylabel('microseconds (1E-9)')

# Make the x-axis ticks formatted to 0 decimal places
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, pos: '%.0f'%x))
plt.show()

5

Gonzalo의 솔루션은 다음을 추가 한 후 나를 위해 작동하기 시작했습니다 set_scientific(False).

ax=gca()
fmt=matplotlib.ticker.ScalarFormatter(useOffset=False)
fmt.set_scientific(False)
ax.xaxis.set_major_formatter(fmt)


4

더 우아한 방법은 티커 포맷터를 사용하는 것입니다. 다음은 x 축과 y 축에 대한 예입니다.

from pylab import *
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

majorLocator   = MultipleLocator(20)
xFormatter = FormatStrFormatter('%d')
yFormatter = FormatStrFormatter('%.2f')
minorLocator   = MultipleLocator(5)


t = arange(0.0, 100.0, 0.1)
s = sin(0.1*pi*t)*exp(-t*0.01)

ax = subplot(111)
plot(t,s)

ax.xaxis.set_major_locator(majorLocator)
ax.xaxis.set_major_formatter(xFormatter)
ax.yaxis.set_major_formatter(yFormatter)

#for the minor ticks, use no labels; default NullFormatter
ax.xaxis.set_minor_locator(minorLocator)

1
이것은 과학적 표기법에 사용되는 오프셋 및 / 또는 계수 를 지정하는 방법에 대한 질문에 대한 답이 아닙니다 .
sodd

@nordev 내 대답이 질문에 구체적으로 대답하지 않더라도 여전히 힌트를 제공합니다. 메시지는 다른 포맷터를 선택하고 내 예제의 날짜 대신 원하는 것을 얻을 수 있다는 것입니다. 과학 세계에서는 줄리안 데이가 표준이거나 내 예에서와 같이 날짜를 사용할 수 있습니다. 제가 제안하려는 것은 다른 접근 방식을 취할 수 있다는 것입니다. 그 사람이 현재 더 나은 아이디어를 가지고 있지 않기 때문에 때때로 질문을 할 수 있습니다. 대체 솔루션을 버리거나 무례하게 취급해서는 안됩니다. 대체로 나는 -1 표를받을 자격이 없었다.
Bogdan

2

두 번째 부분에서는 모든 틱을 다시 수동으로 재설정하지 않고 이것이 내 해결책이었습니다.

class CustomScalarFormatter(ScalarFormatter):
    def format_data(self, value):
        if self._useLocale:
            s = locale.format_string('%1.2g', (value,))
        else:
            s = '%1.2g' % value
        s = self._formatSciNotation(s)
        return self.fix_minus(s)
xmajorformatter = CustomScalarFormatter()  # default useOffset=True
axes.get_xaxis().set_major_formatter(xmajorformatter)

당연히 포맷 문자열을 원하는대로 설정할 수 있습니다.


불행히도 나는 질문의 첫 부분으로 승수를 설정하는 방법을 조사하지 않았습니다.
astrojuanlu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.