matplotlibの日付の目盛りと回転


175

私の日付の目盛りをmatplotlibで回転させようとすると問題が発生します。小さなサンプルプログラムを以下に示します。最後に目盛りを回転させようとすると、目盛りが回転しません。コメント「クラッシュ」の下に示されているようにティックを回転させようとすると、matplot libがクラッシュします。

これは、X値が日付の場合にのみ発生します。への呼び出しでdates変数tを変数に置き換えた場合avail_plotxticks(rotation=70)呼び出しは内部でうまく機能しますavail_plot

何か案は?

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

def avail_plot(ax, x, y, label, lcolor):
    ax.plot(x,y,'b')
    ax.set_ylabel(label, rotation='horizontal', color=lcolor)
    ax.get_yaxis().set_ticks([])

    #crashes
    #plt.xticks(rotation=70)

    ax2 = ax.twinx()
    ax2.plot(x, [1 for a in y], 'b')
    ax2.get_yaxis().set_ticks([])
    ax2.set_ylabel('testing')

f, axs = plt.subplots(2, sharex=True, sharey=True)
t = np.arange(0.01, 5, 1)
s1 = np.exp(t)
start = dt.datetime.now()
dates=[]
for val in t:
    next_val = start + dt.timedelta(0,val)
    dates.append(next_val)
    start = next_val

avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')
plt.subplots_adjust(hspace=0, bottom=0.3)
plt.yticks([0.5,],("",""))
#doesn't crash, but does not rotate the xticks
#plt.xticks(rotation=70)
plt.show()

3
x軸に日付を使用してプロットを作成することは、非常に一般的なタスクです。残念ながら、これほど完全な例はありません。
alexw 2016年

これは重複のない場合、私は思ったんだけどstackoverflow.com/questions/10998621/...
ImportanceOfBeingErnest

回答:


249

非オブジェクト指向のアプローチを希望する場合は、2つの呼び出しの直前に移動plt.xticks(rotation=70)します。たとえば、avail_plot

plt.xticks(rotation=70)
avail_plot(axs[0], dates, s1, 'testing', 'green')
avail_plot(axs[1], dates, s1, 'testing2', 'red')

これにより、ラベルを設定する前に回転プロパティが設定されます。ここには2つの軸plt.xticksがあるため、2つのプロットを作成すると混乱します。plt.xticksが何も実行しない時点でplt.gca()は、変更する軸が提供されないためplt.xticks、現在の軸に作用するは機能しません。

を使用しないオブジェクト指向のアプローチのplt.xticks場合は、

plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )

2つのavail_plot呼び出しの。これにより、正しい軸の回転が明確に設定されます。


11
もう1つの便利なこと:呼び出すときにplt.setp、追加のキーワード引数として指定することにより、複数のパラメーターを設定できます。horizontalalignmentあなたは目盛りラベルを回転させたときにkwargは特に便利です:plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70, horizontalalignment='right' )
8one6

32
このソリューションは、pyplotとオブジェクト指向のアプローチを組み合わせているため、好きではありません。ax.tick_params(axis='x', rotation=70)どこからでも電話できます。
Ted Petrou 2017年

3
@TedPetrouここで「ミキシング」とはどういう意味ですか?plt.setp溶液は完全にオブジェクト指向です。中にいくつかあるという事実が気に入らない場合はpltfrom matplotlib.artist import setp; setp(ax.get_xticklabels(), rotation=90)代わりに使用 してください。
ImportanceOfBeingErnest

@ImportanceOfBeingErnestコードの最初の行plt.xticksは、pyplotです。ドキュメント自体はスタイルを混在させないように言っています。plt.setpより冗長ですが、典​​型的なオブジェクト指向のスタイルでもありません。あなたの答えは間違いなくここで最高です。基本的に、関数を持つものはすべてオブジェクト指向ではありません。インポートするsetpかどうかは関係ありません。
Ted Petrou 2017年

質問のコードの多くはのようyticksにpyplotを使用しており、コードにはavail_plot...の外ではまったくaxが定義されていません
cge

113

ソリューションはmatplotlib 2.1+で機能します

tick_params目盛りのプロパティを変更できるAxesメソッドが存在します。軸メソッドとしても存在しますset_tick_params

ax.tick_params(axis='x', rotation=45)

または

ax.xaxis.set_tick_params(rotation=45)

補足として、現在のソリューションでは、コマンドを使用して、ステートフルインターフェイス(pyplotを使用)とオブジェクト指向インターフェイスを混在させていますplt.xticks(rotation=70)。問題のコードはオブジェクト指向のアプローチを使用しているため、全体を通してそのアプローチに固執するのが最善です。解決策は、plt.setp( axs[1].xaxis.get_majorticklabels(), rotation=70 )


すべてのプロットのデフォルトの回転を変更することは可能ですか?私は私が作るすべてのプロットでこれを変更する必要があると思います。
Chogg

42

ticklabesのループを回避する簡単な解決策は、

fig.autofmt_xdate()

このコマンドは、xaxisラベルを自動的に回転させ、それらの位置を調整します。デフォルト値は、回転角度30°と水平方向の配置 "右"です。しかし、それらは関数呼び出しで変更できます

fig.autofmt_xdate(bottom=0.2, rotation=30, ha='right')

追加のbottom引数はsettingと同等でplt.subplots_adjust(bottom=bottom)、回転した目盛りラベルをホストするために下の軸のパディングをより大きい値に設定できます。

したがって、基本的にここでは、1つのコマンドで適切な日付軸を設定するために必要なすべての設定を利用できます。

良い例は、 matplotlibのページにあります。


正解です。ありがとう!
Abramodj 2017

この関数を介して 'rotation_mode'パラメータを制御できますか?
TheoryX

1
@TheoryXいいえ。rotation_modeが必要な場合は、plt.setpアプローチを使用するか、ティックをループする必要があります(これは基本的に同じです)。
ImportanceOfBeingErnest

はい、それはx軸がグラフの下部にある場合にのみ簡単な解決策です。ただし、x軸がグラフの上部にある場合、または2つのx軸(twinx)が存在する場合は、目盛りと目盛りラベルの間の配置が狂います。その場合、Ted Petrouによる解決策の方が優れています。
Śubham

@Śubham正解。これは主に、最も一般的なケースのための他のすべてのソリューションへのショートカットです。
ImportanceOfBeingErnest

18

適用する別の方法horizontalalignment及びrotation各目盛りラベルにはやってfor変更したい目盛りラベルをループを:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]
hours_value = np.random.random(len(hours))
days_value = np.random.random(len(days))

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
axs[0].plot(hours,hours_value)
axs[1].plot(days,days_value)

for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")

ここに画像の説明を入力してください

そして、これが大目盛りと小目盛りの位置を制御したい場合の例です:

import numpy as np
import matplotlib.pyplot as plt
import datetime as dt

fig, axs = plt.subplots(2)
fig.subplots_adjust(hspace=0.75)
now = dt.datetime.now()
hours = [now + dt.timedelta(minutes=x) for x in range(0,24*60,10)]
days = [now + dt.timedelta(days=x) for x in np.arange(0,30,1/4.)]

axs[0].plot(hours,np.random.random(len(hours)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.HourLocator(byhour = range(0,25,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[0].xaxis.set_major_locator(x_major_lct)
axs[0].xaxis.set_minor_locator(x_minor_lct)
axs[0].xaxis.set_major_formatter(x_fmt)
axs[0].set_xlabel("minor ticks set to every hour, major ticks start with 00:00")

axs[1].plot(days,np.random.random(len(days)))
x_major_lct = mpl.dates.AutoDateLocator(minticks=2,maxticks=10, interval_multiples=True)
x_minor_lct = matplotlib.dates.DayLocator(bymonthday = range(0,32,1))
x_fmt = matplotlib.dates.AutoDateFormatter(x_major_lct)
axs[1].xaxis.set_major_locator(x_major_lct)
axs[1].xaxis.set_minor_locator(x_minor_lct)
axs[1].xaxis.set_major_formatter(x_fmt)
axs[1].set_xlabel("minor ticks set to every day, major ticks show first day of month")
for label in axs[0].get_xmajorticklabels() + axs[1].get_xmajorticklabels():
    label.set_rotation(30)
    label.set_horizontalalignment("right")

ここに画像の説明を入力してください


1
これは私にとってmatplotlib v1.5.1で機能しました(動作中のmatplotlibのレガシーバージョンに行き詰まっています。理由は聞かないでください)
Eddy

私はpython3.6とmatplotlib v2.2.2でテストしたところ、うまくいきました。
Pablo Reyes

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