2017-07-24 7 views
0

Ich versuche, meine erste Grafik mit Matplotlib zu plotten, ich bin neu zu sqlite3 und Matplotlib und normalerweise rrdtool verwenden. Ich habe kein Problem, die Datenbank aufzufüllen oder die Datenbank abzurufen (Dumping), aber ich kann mich nicht um ein Diagramm kümmern. Kannst du mich auf den richtigen Weg bringen, um eine Reihe von Temperaturen und Luftfeuchtigkeit für meine Garage auf einer Timeline grafisch darzustellen?Python sqlite3 und matplotlib plot ersten Graph

Das Format der Tabelle ist:

create table external (temperature float, humidity float, feelslike float, timenow text); 

Ein Auszug aus der Datenbank mit .dump wie folgt aussieht:

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'); 

Meine Funktion

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() 

My Code erzeugt Folgefehler:

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 

Ich vermute es ist die Art, wie es die Daten analysiert?

Antwort

2

Sie haben Recht, dass sqlite3.Cursor.fetchall() eine (möglicherweise leere) Liste von sqlite3.Row abbildbaren/iterierbaren Objekten zurückgibt. Sie haben gerade die Reihenfolge umgekehrt - Sie versuchen, das Temperaturfeld als Datum zu analysieren. Und Ihre values Variable ist nicht definiert.

Versuchen Sie folgendes:

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])) 

Zusätzlich als zusätzlich den Zugriff durch den Index auch Mapping Zugriff von Spaltennamen unterstützt, könnten Sie tun:

for row in data: 
     temperature.append(row['temperature']) 
     humidity.append(row['humidity']) 
     feelslike.append(row['feelslike']) 
     timenow.append(parser.parse(row['timenow'])) 

jedoch Zugriff Index schneller und effizienter.

Zum Plotten müssen Sie mehrmals mit den gleichen x- und anderen y-Daten plot aufrufen. Für Test erzielen ich meinen Datensatz mit:

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)] 

stattdessen eine Datenbank und data = c.fetchall() zu verwenden.

Jetzt haben Sie eine Reihe von float Datenpunkten und zugehörigen datetime.datetime Objekte. Allerdings matplotlib.axes.Axes.plot_date Funktion akzeptiert:

x and/or y can be a sequence of dates represented as float days since 0001-01-01 UTC.

Um das Datum von datetime.datetime Objekt zu konvertieren Tage matplotlib zu schweben, Funktion matplotlib.dates.date2num verwendet.

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") 

Dieser Code erzeugt folgendes Bild: enter image description here

+0

, das funktioniert! Wie gehe ich vor, diese Daten mit mehreren Daten gegen eine Zeitlinie zu zeichnen? Dies ist eindeutig fehlgeschlagen: 'plt.plot_date (Temperatur, Feuchtigkeit, fühlt sich an, '-')' – northwarks

+0

Vielen Dank für eine Erinnerung, ich habe diesen Satz übersehen. Ich habe die Antwort bearbeitet und ein Beispiel für das Plotten hinzugefügt. –

+0

Noch einmal, das funktioniert wirklich gut und genau das, was ich suchte, um mir eine funktionierende Grafik zu geben, kann ich jetzt von lernen, aufbauen und zwicken. – northwarks