Метки по оси X не будут обновляться при масштабировании или панорамировании

#python #matplotlib

#python #matplotlib

Вопрос:

Я пытаюсь создать график с использованием matplotlib, в котором даты будут извлечены из файлов в качестве основного тика, а часы — в качестве второстепенных тиков. В коде, который у меня есть до сих пор, есть это, хотя весь текст сгруппирован — меня это сейчас не беспокоит. Моя проблема в том, что если бы я увеличивал масштаб или панорамировал, тики и их соответствующие значения не обновлялись. Например, если бы я увеличил масштаб до одного дня, все дни по-прежнему отображались на оси x. Я использую Spyder в качестве своей IDE и Python 2.7. Кроме того, я должен просто выбросить это: я новичок как в Python, так и в программировании в целом.

     hticks = []
    tickcnt = 0
    for i in range(len(MBTempvalue)):
    mcnt = mcnt   1
    cnt = cnt   1
    if mcnt == 60:
        mcnt = 0
        harray.append(str(hcnt))
        hcnt = hcnt   1
        tickcnt = tickcnt   1
        hticks.append(tickcnt)
        if hcnt == 24:
            hcnt = 0
    if cnt == 1375:
        cnt = 0
        days = days   1
hours = days * 24
fig = plt.figure(figsize = (8,6))

ax = fig.add_subplot(211)
xmax = float(len(PS0AmbientTempvalue))
dx = hours/xmax
y = PS0AmbientTempvalue
y2 = PS1AmbientTempvalue
x = np.arange(0,hours, dx)
plt.xticks(darray,date)
ax.xaxis.set_major_locator(LinearLocator(len(darray)))
minorLocator = AutoMinorLocator(23)
ax.xaxis.set_minor_locator(minorLocator)
minorformatter = FixedFormatter(harray)
ax.xaxis.set_minor_formatter(minorformatter)

l1, l2, l3, l4 = ax.plot(x,y, 'b', x, PS0AmbientTempavgline, 'r', x, y2, 'y', x, PS1AmbientTempavgline, 'g')
#plt.xlabel('Hours')
plt.ylabel('Temp - C')
plt.title('  PS0/T_AMB and PS1/T_AMB')
plt.axis([0, hours, (minscale1-5), (maxscale1 5)])
plt.grid(True)
fig.legend((l1,l2,l3,l4), ('PS0 Act', 'PS0 Avg', 'PS1 Act', 'PS1 Avg'), 'upper right')
plt.annotate(('PS0 Max = '   PS0AmbientTempstrmax), (0,0), (0, -70), xycoords = 'axes fraction', textcoords = 'offset points', va ='bottom')
plt.annotate(('PS0 Min = '   PS0AmbientTempstrmin), (0,0), (0, -90), xycoords = 'axes fraction', textcoords = 'offset points', va = 'bottom')
plt.annotate(('PS0 Avg = '   PS0AmbientTempstravg), (0,0), (0, -110), xycoords = 'axes fraction', textcoords = 'offset points', va ='bottom')
plt.annotate(('PS0 Stand Dev = '   PS0AmbientTempstrstandev), (0,0), (0, -130), xycoords = 'axes fraction', textcoords = 'offset points', va ='bottom')

plt.annotate(('PS 1Max = '  PS1AmbientTempstrmax), (0,0), (8*hours, -70), xycoords = 'axes fraction', textcoords = 'offset points', va = 'bottom')
plt.annotate(('PS1 Min = '   PS1AmbientTempstrmin), (0,0), (8*hours, -90), xycoords = 'axes fraction', textcoords = 'offset points', va = 'bottom')
plt.annotate(('PS1 Avg = '   PS1AmbientTempstravg), (0,0), (8*hours, -110), xycoords = 'axes fraction', textcoords = 'offset points', va = 'bottom')
plt.annotate(('PS1 Stand Dev = '   PS1AmbientTempstrstandev), (0,0), (8*hours, -130), xycoords = 'axes fraction', textcoords = 'offset points', va = 'bottom')
  

Любая помощь будет принята с благодарностью.
Спасибо!
Крис

Ответ №1:

Причина, по которой они не обновляются, заключается в том, что вы используете a FixedFormatter , которые, как следует из названия, исправлены. Основная задача для этого — наложение текстовых меток на метки (например, создание столбчатых графиков, где ось x является качественной, а не количественной). mpl делает именно то, что вы ему сказали.

matplotlib может напрямую отображать datetime объекты, что, вероятно, и является тем, что вы хотите сделать здесь.

См. api и кулинарную книгу.

 import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import datetime

numdays = 5
base = datetime.datetime.today()
date_list = [base - datetime.timedelta(hours=x) for x in range(0, numdays*24)]


data = np.random.rand(len(date_list))

fig, ax = plt.subplots(1, 1)
ax.plot(date_list, data)
ax.xaxis.set_major_locator(mdates.DayLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_minor_locator(mdates.HourLocator())
fig.autofmt_xdate()

plt.draw()
plt.show()
  

введите описание изображения здесь

Комментарии:

1. Человек! Это было ОЧЕНЬ полезно! Я совсем не знаком с методом datetime. Есть ли способ изменить его так, чтобы вместо бесконечного обратного отсчета он отсчитывался до определенной даты? Например, у меня будет дата начала и дата остановки.

2. Я действительно не понимаю, что вы пытаетесь сделать.

3. Я новичок, поэтому, вероятно, использую не самые лучшие слова для описания моей ситуации. Извините. У пользователя будет диапазон файлов, в которых даты ввода данных являются частью имени файла. На основе выбора пользователем этого диапазона определяется количество дней, которые я хочу отобразить, и многим из этих файлов 4 года. Итак, я предполагаю, что я говорю, что даты будут определяться пользователем — они будут переменными. На самом деле, что у меня есть на данный момент, так это то, что диапазон дат находится в списке, в котором я собирался, чтобы первый элемент был начальной датой, а последний элемент — датой остановки.

Ответ №2:

Большое спасибо tcaswell за помощь! Я бы не смог решить свою проблему без вашей помощи! Вот код, который я использую:

 def kuVpolFunc2(kuvdate, kuvit, kuviti, kuvfp, kuvfpi, faultflag):
import matplotlib.pyplot as plt
import numpy as np
import re
import matplotlib.dates as mdates
import datetime    
from datetime import timedelta   
kutempvalue = kuvit
kutempinter = kuviti
kufpvalue = kuvfp
kufpinter = kuvfpi
faultflagit = faultflag
date = kuvdate

datelist = []
#I first had to decontruct the filename pulled from the directory to put it in a format that Python could then create a datetime object.
for n in date:
    month = n[:3]    
    datenum = re.sub("[^0-9]","", n)
    day = str(datenum[:-4])
    year = str(datenum[2:])
    print ("Year:  "   year)
    print ("Month:  "   month)
    print ("Day:  "   day)
    alltogether = str(month   ' '   day   ' '   year)

    dateobject = datetime.datetime.strptime(alltogether, '%b %d %Y')
    datelist.append(dateobject)
start = min(datelist)
dlist = [start   timedelta(minutes = x) for x in range(0, len(datelist) *1440)]

#The 'add' variable is used to make sure that the dlist's dimension is the same as the           data.  It isn't posted here for brevity's sake, but I can post it if someone wants it.
add = max(dlist)



fig, ax = plt.subplots(1,1)
l1, l2, = ax.plot(dlist, y, 'b', dlist, kutempavgline, 'r')
ax.xaxis.set_major_locator(mdates.DayLocator())
plt.title('Ku_Vpol Internal Temp')
plt.ylabel('Temp - C')
fig.legend((l1,l2), ('Internal Temp Actual Temp', 'Internal Temp Average Temp'), 'upper       right')
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))
ax.xaxis.set_minor_locator(mdates.HourLocator())

plt.grid(True)
fig.autofmt_xdate()
plt.draw()   
plt.show()