matplotlib:軸のオフセット値を整数または特定の数にフォーマットする


92

常にナノ秒(1e-9)と呼ばれるデータをプロットしているmatplotlibの図があります。y軸に、数十ナノ秒のデータがある場合、つまり 44e-9の場合、軸の値は4.4と表示され、+ 1e-8がオフセットとして表示されます。とにかく、軸に+ 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関数は、単位変換の線に沿ったもののようです。ヒントをありがとう、それは私が今探している他のいくつかの解決策に私を導きました!
ジョナサン

1
rcParamsデフォルトでオフになっている場合はオフにすることを検討してください。rcParams["axes.formatter.useoffset"] = Falseここでは、stackoverflow.com
Ruggero Turra

回答:


100

私はまったく同じ問題を抱えていて、これらの行は問題を修正しました:

from matplotlib.ticker import ScalarFormatter

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

1
これは迅速かつ簡単な答えです。ありがとうございました。
maxm 2013

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オフセットをフォーマットするのかわかりません。オフセットの大きさは問題ありませんが、非指数値として表示する必要があるだけです。
ジョナサン

ワオ。どのようにして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軸のオフセットを保持したいのですが、指数として表示されないようにオフセットの値をフォーマットします。
ジョナサン

これは私のために働いた唯一の方法です!ありがとう:)
海洋科学者

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

ゴンザロのソリューションは、追加した後に私のために働き始めましたset_scientific(False)

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


4

よりエレガントな方法は、ティッカーフォーマッターを使用することだと思います。以下は、xaxisとyaxisの両方の例です。

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 2013

@nordev私の答えが質問に明確に答えていなくても、それでもヒントが得られます。メッセージは、別のフォーマッターを選択して、私の例から日付の代わりに必要なものを取得できることです。科学の世界では、ユリウス日が標準ですが、私の例のように日付を使用することもできます。私が提案しようとしていたことは、別のアプローチを取ることができるということです。その人は現時点でより良いアイデアを持っていないので、時々質問がされるかもしれません。代替ソリューションは、破棄したり、軽視したりしないでください。全体として、私は-1票に値しませんでした。
ボグダン2014年

2

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 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.