5

matplotlib を使用して PDF 出力用に flotr2 で最初に作成されたプロットされたグラフを複製しようとしました。flotrの方が使いやすいと言わざるを得ません...しかし、それはさておき-現在、x軸の日付/時刻を目的の形式にフォーマットしようとしているところに行き詰まっています。これは、期間が2時間ごとの時間:分ですx 軸は 1 日未満で、期間が 1 日より長い場合は年月日の形式で、間隔は 1 日です。

私は多くの例を読み、それらをコピーしようとしましたが、結果は同じままで、期間の長さに基づいて1〜3時間の間隔で時間:分:秒です。ここに画像の説明を入力

私のコード:

colorMap = {
        'speed': '#3388ff',
        'fuel': '#ffaa33',
        'din1': '#3bb200',
        'din2': '#ff3333',
        'satellites': '#bfbfff'
}

otherColors = ['#00A8F0','#C0D800','#CB4B4B','#4DA74D','#9440ED','#800080','#737CA1','#E4317F','#7D0541','#4EE2EC','#6698FF','#437C17','#7FE817','#FBB117']

plotMap = {}

import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as dates
fig = plt.figure(figsize=(22, 5), dpi = 300, edgecolor='k')
ax1 = fig.add_subplot(111)

realdata = data['data']
keys = realdata.keys()
if 'speed' in keys:
    speed_index = keys.index('speed')
    keys.pop(speed_index)
    keys.insert(0, 'speed')

i = 0
for key in keys:
    if key not in colorMap.keys():
        color = otherColors[i]
        otherColors.pop(i)
        colorMap[key] = color
        i += 1

label = u'%s' % realdata[keys[0]]['name']
ax1.set_ylabel(label)

plotMap[keys[0]] = {}
plotMap[keys[0]]['label'] = label

first_dates = [ r[0] for r in realdata[keys[0]]['data']]

date_range = first_dates[-1] - first_dates[0]


ax1.xaxis.reset_ticks()

if date_range > datetime.timedelta(days = 1):
    ax1.xaxis.set_major_locator(dates.WeekdayLocator(byweekday = 1, interval=1))
    ax1.xaxis.set_major_formatter(dates.DateFormatter('%Y-%m-%d'))
else:
    ax1.xaxis.set_major_locator(dates.HourLocator(byhour=range(24), interval=2))
    ax1.xaxis.set_major_formatter(dates.DateFormatter('%H:%M'))

ax1.xaxis.grid(True)

plotMap[keys[0]]['plot'] = ax1.plot_date(
                                dates.date2num(first_dates), 
                                [r[1] for r in realdata[keys[0]]['data']], colorMap[keys[0]], xdate=True)

if len(keys) > 1:
    first = True
    for key in keys[1:]:
        if first:
            ax2 = ax1.twinx()
            ax2.set_ylabel(u'%s' % realdata[key]['name'])
            first = False
        plotMap[key] = {}
        plotMap[key]['label'] = u'%s' % realdata[key]['name']
        plotMap[key]['plot'] = ax2.plot_date(
                                    dates.date2num([ r[0] for r in realdata[key]['data']]), 
                                    [r[1] for r in realdata[key]['data']], colorMap[key], xdate=True)


plt.legend([value['plot'] for key, value in plotMap.iteritems()], [value['label'] for key, value in plotMap.iteritems()], loc = 2)

plt.savefig(path +"node.png", dpi = 300, bbox_inches='tight')

なぜ私が望ましい結果を得られないのか、誰かが指摘できますか?

編集1:

プロット後に書式設定ブロックを移動したところ、より良い結果が得られているようです。しかし、それらは今でも望ましい結果です。期間が 1 日未満の場合、2 時間ごと (間隔 = 2) にティックを取得しますが、これらのティックを不均等な時間ではなく偶数時間に取得できればと思います。それは可能ですか?

if date_range > datetime.timedelta(days = 1):
    xax.set_major_locator(dates.DayLocator(bymonthday=range(1,32), interval=1))
    xax.set_major_formatter(dates.DateFormatter('%Y-%m-%d'))
else:
    xax.set_major_locator(dates.HourLocator(byhour=range(24), interval=2))
    xax.set_major_formatter(dates.DateFormatter('%H:%M'))

Edit2:これは私が欲しかったものを私に与えるように見えました:

if date_range > datetime.timedelta(days = 1):
    xax.set_major_locator(dates.DayLocator(bymonthday=range(1,32), interval=1))
    xax.set_major_formatter(dates.DateFormatter('%Y-%m-%d'))
else:
    xax.set_major_locator(dates.HourLocator(byhour=range(0,24,2)))
    xax.set_major_formatter(dates.DateFormatter('%H:%M'))

アラン

4

2 に答える 2

10

あなたはあなたが必要とするよりもあなた自身でこの方法を難しくしています。 matplotlibオブジェクトに対して直接プロットできdatetimeます。問題は、ロケーターを設定してからプロットしていることであり、プロットによってロケーター/フォーマッターがデフォルトの自動バージョンに置き換えられていると思われます。ロケーターに関するロジックのブロックをプロットループの下に移動してみてください。

これはあなたのコードのかなりの部分を置き換えることができると思います:

d = datetime.timedelta(minutes=2)
now =  datetime.datetime.now()
times = [now + d * j for j in range(500)]
ax = plt.gca() # get the current axes
ax.plot(times, range(500))

xax = ax.get_xaxis() # get the x-axis
adf = xax.get_major_formatter() # the the auto-formatter


adf.scaled[1./24] = '%H:%M'  # set the < 1d scale to H:M
adf.scaled[1.0] = '%Y-%m-%d' # set the > 1d < 1m scale to Y-m-d
adf.scaled[30.] = '%Y-%m' # set the > 1m < 1Y scale to Y-m
adf.scaled[365.] = '%Y' # set the > 1y scale to Y

plt.draw()

のドキュメントAutoDateFormatter

于 2013-01-22T05:44:02.013 に答える
9

これを行うことで、私が望んでいたことを達成しました:

if date_range > datetime.timedelta(days = 1):
    xax.set_major_locator(dates.DayLocator(bymonthday=range(1,32), interval=1))
    xax.set_major_formatter(dates.DateFormatter('%Y-%m-%d'))
else:
    xax.set_major_locator(dates.HourLocator(byhour=range(0,24,2)))
    xax.set_major_formatter(dates.DateFormatter('%H:%M'))
于 2013-06-06T17:17:34.690 に答える