在matplotlib中绘制日期,一个绘图工作,另一个绘图没有

时间:2017-07-12 22:27:09

标签: python datetime matplotlib

我试图用matplotlib在python中绘制一些带有相应时间戳的数据。 'dates'实际上是datetime.time对象(所以没有相应的日期,我不关心日期),如下所示:

In[6]: dates[1]
Out[6]: datetime.time(12, 3, 1) 

我创建了一个简单的代码,显示了我想要做的事情(并且正在处理实际数据,但由于某些原因无效):

工作代码

import matplotlib.pyplot as plt
import matplotlib.dates as pltdt
import datetime as dt

dates = [dt.time(12,3,i) for i in range(6)]
time_to_datetime = []
for i in dates:
    time_to_datetime.append(dt.datetime.combine(dt.date.min, i))
dates_as_num = pltdt.date2num(time_to_datetime)
values = range(len(dates))

plt.plot_date(dates_as_num, values)
plt.show()

print ('Done!')

产生以下情节:

Example of what I want

然而,当我用我的数据做这个精确的过程时(当然不是6点我有~300,000并且还有一些额外的处理)我收到以下错误:

Traceback (most recent call last):
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 197, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\figure.py", line 1143, in draw
    renderer, self, dsu, self.suppressComposite)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axes\_base.py", line 2409, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 1136, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in <listcomp>
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 912, in iter_ticks
    majorLocs = self.major.locator()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 983, in __call__
    self.refresh()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 1003, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 760, in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 401, in num2date
    return _from_ordinalf(x, tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 254, in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix).replace(tzinfo=UTC)
ValueError: ordinal must be >= 1
Traceback (most recent call last):
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_qt5agg.py", line 197, in __draw_idle_agg
    FigureCanvasAgg.draw(self)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\backends\backend_agg.py", line 464, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\figure.py", line 1143, in draw
    renderer, self, dsu, self.suppressComposite)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axes\_base.py", line 2409, in draw
    mimage._draw_list_compositing_images(renderer, self, dsu)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\image.py", line 139, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\artist.py", line 63, in draw_wrapper
    draw(artist, renderer, *args, **kwargs)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 1136, in draw
    ticks_to_draw = self._update_ticks(renderer)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in _update_ticks
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 969, in <listcomp>
    tick_tups = [t for t in self.iter_ticks()]
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\axis.py", line 912, in iter_ticks
    majorLocs = self.major.locator()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 983, in __call__
    self.refresh()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 1003, in refresh
    dmin, dmax = self.viewlim_to_dt()
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 760, in viewlim_to_dt
    return num2date(vmin, self.tz), num2date(vmax, self.tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 401, in num2date
    return _from_ordinalf(x, tz)
  File "C:\Users\Will Evonosky\AppData\Local\Enthought\Canopy\edm\envs\User\lib\site-packages\matplotlib\dates.py", line 254, in _from_ordinalf
    dt = datetime.datetime.fromordinal(ix).replace(tzinfo=UTC)
ValueError: ordinal must be >= 1
%run "c:\users\willev~1\appdata\local\temp\tmpjkubsr.py"

我已经尽了一切努力让这件事没有成功。我甚至尝试将时间转换为字符串,只是手动设置x轴的刻度标签,但遇到了一个问题,即x轴上显示的内容并未准确表示实际日期(应该有200分钟)在显示的分钟间隔中,即使y值跨越整个200点范围,也总共显示3分钟。谢谢你的帮助!

我的修剪后的代码如下(抱歉它很乱):

import matplotlib.pyplot as plt
import matplotlib.dates as pltdt
import numpy as np
import datetime as dt
import math

def plot_two_orbit(times, values):
    fig2 = plt.figure(figsize = (14,8))
    ax2=plt.subplot(111)
    ax2.plot_date(times, values, linewidth=4)
    ax2.set_xticklabels([i.strftime('%H:%M') for i in two_orbit_times])
    ax2.yaxis.set_ticks_position("left")
    ax2.xaxis.set_ticks_position("bottom")
    ax2.spines['top'].set_color('None')
    ax2.spines['right'].set_color('None')
    ax2.spines['bottom'].set_color('black')
    ax2.spines['left'].set_color('black')
    ax2.tick_params(axis='x', colors='black', labelsize=20, pad=10)
    ax2.tick_params(axis='y', colors='black', labelsize=20, pad=10)
    ax2.yaxis.label.set_color('black')
    ax2.xaxis.label.set_color('black')
    ax2.set_ylabel(r'Ion Temp (K)', size=23)
    ax2.set_xlabel(r'Local Time', size=23)
    plt.show()
    return None

#model parameters
modalt = np.arange(90, 1005, 5) #90km to 1000km in 5km increiments,
modlat = np.arange(-90, 92, 2) #latitude from 0 to 355 in 5 degree incriments
modlon = np.arange(0,356, 4) #longitude from -87.5 to 87.5 in 5 degree incriments
modtime = np.arange(.25,24.25,.25) # time in 15 minute incriments

#making the modtime array into a python datetime.time object
times = []
for i in modtime:
    strip = [math.modf(i)[1],math.modf(i)[0]*60 ]
    if strip[0]==24:
        times.append(dt.time(0, int(strip[1]),0))
    else:
        times.append(dt.time(int(strip[0]), int(strip[1]),0))

#loading in the Model data
mdatas =np.load('C:/Users/Will Evonosky/Dropbox/SOARS/SOARS 2017/Data/GIP_Feb5_ti.npy')

#Function to find the index of the neasrest array point to a given value
def find_nearest(array,value):
    idx = (np.abs(array-value)).argmin()
    return idx

#load in the ephemeris data retrieved from STK 
ephem = np.genfromtxt('C:/Users/Will Evonosky/Dropbox/SOARS/SOARS 2017/Data/STK Data/Location for count and science/Times_Loc_Fix_7mon_500km.csv', skip_header=1, dtype=None, delimiter=',')

#Pulling out the indivdual parameters from the STK data
sattime = [dt.datetime.strptime(i[1].decode('ascii'), '%H:%M').time() for i in ephem]
satlat = np.round([i[2] for i in ephem], decimals=2)
satlon = np.round([i[3] for i in ephem], decimals=2)
satalt = np.round([i[4] for i in ephem], decimals=2)

#making the modeled satellite longitude match GIP (-180 to 180) to (0 to 360)
satloncor = []
for i in satlon:
    if i<0:
        satloncor.append(round(i+360,2))
    else:
        satloncor.append(round(i,2))

#Converting UT times for satellite data into local solar time

localtimes = []
for (i,j) in zip(sattime, satloncor):
    td = dt.datetime.combine(dt.datetime.min, i) - dt.datetime.min
    seconds = td  // dt.timedelta(seconds=1)
    local = (seconds + (j/(360/86400)))/3600
    if local>24:
        local-=24
    strip = [math.modf(local)[1],math.modf(local)[0]*60 ]
    if strip[0]==24:
        localtimes.append(dt.time(0, int(strip[1]),0))
    else:
        localtimes.append(dt.time(int(strip[0]), int(strip[1]),0))

#Creating empty arrays to hold the resulting values
grid_night_hour = np.zeros((24,len(modlat),len(modlon)))
two_orbit_line = []
two_orbit_times=[]

#Count determines how many orbits to sample. 1 orbit is ~ 90 data points
count = 200
night_hours = [20,21,22,23,0,1,2,3,4,5]
#plucking out the model data which most closely match the lat, lon, time, and alt of STK sat data
for (i,j,k,l,m) in zip(satlat, satloncor, sattime, satalt, localtimes):
    mlat = find_nearest(modlat, i)
    mlon = find_nearest(modlon, j)
    malt = find_nearest(modalt, l)
    mtime = times.index(min(times, key=lambda d: abs(dt.datetime.combine(dt.date.min,d) - dt.datetime.combine(dt.date.min,k))))
    if m.hour in night_hours:
        grid_night_hour[m.hour, mlat, mlon] = mdatas[malt, mlat, mlon, mtime]
    if count > 0:
        two_orbit_line.append(mdatas[malt, mlat, mlon, mtime])
        two_orbit_times.append(pltdt.date2num(dt.datetime.combine(dt.date.min,m)))
        count-=1

#masking zero values so they wont plot
grid_night_hour[grid_night_hour == 0.0] = np.nan

grid_night_hour = grid_night_hour - np.nanmean(grid_night_hour)

#Plotting the data

plot_two_orbit(two_orbit_times, two_orbit_line)

print ('Done!')

1 个答案:

答案 0 :(得分:1)

我明白了。即使他们的提法不正确,Y.Luo仍在正确的轨道上。我认为pythons datetime库支持的最小年份对于matploltib识别的日期来说太低了,并且最大年份也是如此。我手动插入了一个日期(下面更改了代码),情节突然起作用。现在我遇到了另一个问题,但那将是另一个问题。

if count > 0:
        two_orbit_line.append(mdatas[malt, mlat, mlon, mtime])
        two_orbit_times.append(pltdt.date2num(dt.datetime.combine(dt.date(2019,1,1),m)))
        count-=1