我试图用matplotlib绘制我的第一个图表,我是sqlite3和matplotlib的新手,通常使用rrdtool。我没有填充数据库或检索(转储)数据库的问题,但我无法理解创建图表。你能否把我放在正确的路径上,在时间轴上为我的车库绘制一系列温度和湿度?
表的格式为:
create table external (temperature float, humidity float, feelslike float, timenow text);
使用数据库中的.dump提取的内容如下:
INSERT INTO "external" VALUES(17.0,68.0,11.6,'2017-07-24 12:24:02.578014');
INSERT INTO "external" VALUES(17.7,68.0,12.3,'2017-07-24 12:34:02.590939');
INSERT INTO "external" VALUES(17.7,68.0,12.3,'2017-07-24 12:44:02.585097');
INSERT INTO "external" VALUES(17.7,68.0,12.3,'2017-07-24 12:54:02.594123');
INSERT INTO "external" VALUES(18.3,63.0,12.8,'2017-07-24 13:04:02.586191');
INSERT INTO "external" VALUES(18.3,63.0,12.8,'2017-07-24 13:14:02.566619');
我的功能
import sqlite3
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from dateutil import parser
from matplotlib import style
def graph_data():
# Connect to database
now = datetime.now()
sqlite_file = '/home/pi/scripts/database/climate.db'
conn = sqlite3.connect(sqlite_file)
c = conn.cursor()
style.use('fivethirtyeight')
c.execute('SELECT temperature, humidity, feelslike, timenow FROM external')
data = c.fetchall()
temperature = []
humidity = []
feelslike = []
timenow = []
for row in data:
timenow.append(parser.parse(row[0]))
values.append(row[1])
plt.plot_date(temperature, humidity, feelslike,'-')
plt.savefig('/home/pi/scripts/database/foo.png')
c.close()
conn.close()
我的代码产生以下错误:
Traceback (most recent call last):
File "test.py", line 364, in <module>
graph_data()
File "test.py", line 323, in graph_data
timenow.append(parser.parse(row[0]))
File "/usr/local/lib/python2.7/dist-packages/dateutil/parser.py", line 1168, in parse
return DEFAULTPARSER.parse(timestr, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/dateutil/parser.py", line 556, in parse
res, skipped_tokens = self._parse(timestr, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/dateutil/parser.py", line 675, in _parse
l = _timelex.split(timestr) # Splits the timestr into tokens
File "/usr/local/lib/python2.7/dist-packages/dateutil/parser.py", line 192, in split
return list(cls(s))
File "/usr/local/lib/python2.7/dist-packages/dateutil/parser.py", line 61, in __init__
'{itype}'.format(itype=instream.__class__.__name__))
TypeError: Parser must be a string or character stream, not float
我猜它解析日期的方式?
答案 0 :(得分:3)
你是正确的sqlite3.Cursor.fetchall()
返回sqlite3.Row
可映射/可迭代对象的一个(可能是空的)列表,你只是颠倒了顺序 - 你试图将温度字段解析为日期。
而且您的values
变量未定义。
试试这个:
c.execute('SELECT temperature, humidity, feelslike, timenow FROM external')
data = c.fetchall()
# data[*][0] = temperature
# data[*][1] = humidity
# data[*][2] = feelslike
# data[*][3] = timenow
temperature = []
humidity = []
feelslike = []
timenow = []
for row in data:
temperature.append(row[0])
humidity.append(row[1])
feelslike.append(row[2])
timenow.append(parser.parse(row[3]))
此外,由于Row
除了按索引访问外,还支持按列名进行映射访问,您可以这样做:
for row in data:
temperature.append(row['temperature'])
humidity.append(row['humidity'])
feelslike.append(row['feelslike'])
timenow.append(parser.parse(row['timenow']))
然而,索引访问速度更快,效率更高。
对于绘图,您需要多次调用plot
,每次都使用相同的x和不同的y数据。为了测试,我用:
random.seed(0)
data = [(random.uniform(10, 25),
random.uniform(70, 99),
random.uniform(15, 30),
"2017-07-24 12:{:02d}:00.{:06d}".format(i, i * 1000 + int(random.uniform(0, 50)))
) for i in range(10)]
而不是使用数据库和data = c.fetchall()
。
现在您有一组float
个数据点和关联的datetime.datetime
个对象。但是,matplotlib.axes.Axes.plot_date
函数接受:
x和/或y可以是表示为浮动天数的日期序列 0001-01-01 UTC。
要将日期从datetime.datetime
对象转换为matplotlib的浮动天数,请使用函数matplotlib.dates.date2num
。
for row in data:
temperature.append(row[0])
humidity.append(row[1])
feelslike.append(row[2])
timenow.append(parser.parse(row[3]))
# Convert datetime.datetime to float days since 0001-01-01 UTC.
dates = [date2num(t) for t in timenow]
fig = plt.figure()
ax1 = fig.add_subplot(111)
ax1.set_title("My environmental data")
# Configure x-ticks
ax1.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y %H:%M'))
# Plot temperature data on left Y axis
ax1.set_ylabel("Temperature [°C]")
ax1.plot_date(dates, temperature, '-', label="Temperature", color='r')
ax1.plot_date(dates, feelslike, '-', label="Feels like", color='b')
# Plot humidity data on right Y axis
ax2 = ax1.twinx()
ax2.set_ylabel("Humidity [% RH]")
ax2.plot_date(dates, humidity, '-', label="Humidity", color='g')
# Format the x-axis for dates (label formatting, rotation)
fig.autofmt_xdate(rotation=60)
fig.tight_layout()
# Show grids and legends
ax1.grid(True)
ax1.legend(loc='best', framealpha=0.5)
ax2.legend(loc='best', framealpha=0.5)
plt.savefig("figure.png")