date2num,值错误:序数必须 >= 1
我正在使用matplotlib的蜡烛图模块,这个模块要求时间以浮点数的天数格式传入。我在使用date2num函数来进行转换,代码如下:
这是我的代码:
import csv
import sys
import math
import numpy as np
import datetime
from optparse import OptionParser
import matplotlib.pyplot as plt
import matplotlib.cbook as cbook
import matplotlib.mlab as mlab
import matplotlib.dates as mdates
from matplotlib.finance import candlestick
from matplotlib.dates import date2num
datafile = 'historical_data/AUD_Q10_1D_500.csv'
print 'loading', datafile
r = mlab.csv2rec(datafile, delimiter=';')
quotes = [date2num(r['date']),r['open'],r['close'],r['max'],r['min']]
candlestick(ax, quotes, width=0.6)
plt.show()
(这里是csv文件:http://db.tt/MIOqFA0)
文档上是这么说的:
candlestick(ax, quotes, width=0.20000000000000001, colorup='k', colordown='r', alpha=1.0) quotes是一个包含(时间,开盘价, 收盘价,最高价,最低价,...)的元组列表。只要元组的前五个元素是这些值,元组的长度可以随意(例如可以存储成交量)。 时间必须是浮点数的天数格式 - 请查看date2num
这是完整的错误日志:
Traceback (most recent call last):
File
"/usr/lib/python2.6/site-packages/matplotlib/backends/backend_qt4agg.py",
line 83, in paintEvent
FigureCanvasAgg.draw(self) File
"/usr/lib/python2.6/site-packages/matplotlib/backends/backend_agg.py",
line 394, in draw
self.figure.draw(self.renderer) File
"/usr/lib/python2.6/site-packages/matplotlib/artist.py",
line 55, in draw_wrapper draw(artist,
renderer, *args, **kwargs) File
"/usr/lib/python2.6/site-packages/matplotlib/figure.py",
line 798, in draw func(*args) File
"/usr/lib/python2.6/site-packages/matplotlib/artist.py",
line 55, in draw_wrapper draw(artist,
renderer, *args, **kwargs) File
"/usr/lib/python2.6/site-packages/matplotlib/axes.py", line 1946, in draw a.draw(renderer)
File
"/usr/lib/python2.6/site-packages/matplotlib/artist.py",
line 55, in draw_wrapper draw(artist,
renderer, *args, **kwargs) File
"/usr/lib/python2.6/site-packages/matplotlib/axis.py", line 971, in draw tick_tups = [ t for
t in self.iter_ticks()] File
"/usr/lib/python2.6/site-packages/matplotlib/axis.py", line 904, in iter_ticks majorLocs =
self.major.locator() File
"/usr/lib/python2.6/site-packages/matplotlib/dates.py",
line 743, in __call__ self.refresh()
File
"/usr/lib/python2.6/site-packages/matplotlib/dates.py",
line 752, in refresh dmin, dmax =
self.viewlim_to_dt() File
"/usr/lib/python2.6/site-packages/matplotlib/dates.py",
line 524, in viewlim_to_dt return
num2date(vmin, self.tz),
num2date(vmax, self.tz) File
"/usr/lib/python2.6/site-packages/matplotlib/dates.py",
line 289, in num2date if not
cbook.iterable(x): return
_from_ordinalf(x, tz) File "/usr/lib/python2.6/site-packages/matplotlib/dates.py",
line 203, in _from_ordinalf dt =
datetime.datetime.fromordinal(ix)
ValueError: ordinal must be >= 1
如果我快速运行一下:
for x in r['date']:
print str(x) + "is :" + str(date2num(x))
它输出的内容类似于:
2010-06-12is :733935.0
2010-07-12is :733965.0
2010-08-12is :733996.0
这听起来对我来说没问题 :)
3 个回答
我觉得你的问题出在这里:
r = mlab.csv2rec(datafile, delimiter=';')
你需要跳过csv文件的第一行,这意味着你需要:
r = mlab.csv2rec(datafile, delimiter=';', skiprows=1)
从技术上讲,这个说法不太准确,Ubuntu上有一个旧版本的库,而提问者的版本有下面这两行,但这是我最初的回答
我建议你确保使用的是最新版本的matplotlib。
为了能重现这个问题,我下载并安装了最新版本,发现出问题的代码行号变成了179。我还注意到在调用fromordinal之前,值被转换成了整数(这让senderle的回答更有说服力)。
(在Ubuntu库中,最新的matplotlib的第178-179行)
ix = int(x)
dt = datetime.datetime.fromordinal(ix)
如果升级不行,那你应该先把值转换成整数。
看起来你传入的是一个浮点数。在你提供的错误信息中(下次请提供完整的错误信息!),似乎matplotlib只是把转换的工作交给了datetime.datetime.fromordinal
来处理。
我没有Python 3的环境来测试这个,不过在我尝试用Python 2.6的datetime.datetime.fromordinal
把浮点数转换成datetime
对象时,收到了一个弃用警告。然后我在ideone上试了一下,得到了这个结果:
Traceback (most recent call last):
File "prog.py", line 2, in <module>
print(datetime.datetime.fromordinal(5.5))
TypeError: integer argument expected, got float
所以可能是浮点数让它卡住了。
仔细看看文档说明哦 :)
quotes 是一个包含 (时间, 开盘价, 收盘价, 最高价, 最低价, ...) 元组的列表。
这里的意思是,它希望 quotes 中的每一个项目都是一个包含 (时间, 开盘价, 收盘价, 最高价, 最低价) 的序列。
你传入的是5个长数组,但它其实需要的是一个包含5个项目的长序列。
你只需要用 zip
把你的输入合并一下就可以了。
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab
from matplotlib.finance import candlestick
from matplotlib.dates import date2num
datafile = 'Downloads/AUD_Q10_1D_500.csv'
r = mlab.csv2rec(datafile, delimiter=';')
quotes = zip(date2num(r['date']),r['open'],r['close'],r['max'],r['min'])
fig, ax = plt.subplots()
candlestick(ax, quotes, width=0.6)
plt.show()