Matplotlib IndexError: list index out of range

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Mittwoch 15. August 2018, 19:23

Hallo,
ich habe das Problem bei meinem Code der Werte aus einer Csv Datei auslesen soll und als subplot darstellen soll, dass die beiden Zeilen 17 und 18 den Fehler IndexError: list index out of range im Debugger anzeigen, jedoch eigentlich bis auf den wert von "zeile" genau gleich wie zeile 16 aufgebaut sind. Kann mir jemand sagen woran das liegt?
Python

Code: Alles auswählen

import matplotlib.pyplot as plt

dateihandler = open('test.csv')

inhalt = dateihandler.read()

zeilen = inhalt.split('\n')

tabelle = []

for zeile in range(len(zeilen)):
    spalten = zeilen[zeile].split(',')
    tabelle.append(spalten)
    tabelle[zeile][1:] = [float(zahl) for zahl in tabelle[zeile][1:]]

time = [zeile[0] for zeile in tabelle]
luftfeuchtedrin = [zeile[1] for zeile in tabelle]
luftfeuchteausen = [zeile[3] for zeile in tabelle]

fig, ax = plt.subplots()
ax.plot(time, luftfeuchteausen, label="luftfeuchteausen")
ax.plot(time, luftfeuchtedrin, label="luftfeuchtedrin")
ax.legend()

plt.show()

pass
csv:

Code: Alles auswählen

2018-08-13 14:00:00,71.60,22.20,53.10,22.50,834,225.00
2018-08-13 15:00:00,60.40,23.40,54.20,23.40,830,230.00
2018-08-13 16:00:00,64.30,21.30,53.60,24.30,835,231.67
2018-08-13 17:00:00,62.50,26.90,59.50,26.90,829,742.75
2018-08-13 18:00:00,71.60,18.80,57.30,21.20,827,3643.33
2018-08-13 19:00:00,60.40,22.60,56.90,22.50,833,4084.17
2018-08-13 20:00:00,64.30,25.50,56.80,26.90,826,4517.17
2018-08-13 21:00:00,62.50,26.90,64.60,23.40,840,4342.92
Sirius3
User
Beiträge: 8254
Registriert: Sonntag 21. Oktober 2012, 17:20

Mittwoch 15. August 2018, 19:43

Hat schon jemand erwähnt, dass Du das csv-Modul benutzen sollst? Ansonsten würde man über das Datei-Objekt direkt iterieren, statt die Datei komplett zu lesen, an den Zeileumbruchzeilen zu splitten und danach über den Index zu iterieren. Auch erst die komplette Zeile einer Liste hinzuzufügen und dann einen Teil davon in floats umzuwandeln, ist umständlich. Und die Zeile nach dem letzten Zeileumbruchzeichen scheint wohl leer zu sein. Ein einfach so rumstehendes `pass` ist unsinnig.

Code: Alles auswählen

import csv
import matplotlib.pyplot as plt

with open('test.csv') as lines:
    reader = csv.reader(lines, delimiter=',')
    tabelle = [
        row[:1] + [float(c) for c in row[1:]]
        for row in reader
    ] 

time = [zeile[0] for zeile in tabelle]
luftfeuchtedrin = [zeile[1] for zeile in tabelle]
luftfeuchteausen = [zeile[3] for zeile in tabelle]

fig, ax = plt.subplots()
ax.plot(time, luftfeuchteausen, label="luftfeuchteausen")
ax.plot(time, luftfeuchtedrin, label="luftfeuchtedrin")
ax.legend()
fig.show()
Benutzeravatar
__blackjack__
User
Beiträge: 1031
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 15. August 2018, 20:58

Für Zeitreihen ist `pandas` auch immer ganz nett zu benutzen:

Code: Alles auswählen

from matplotlib import pyplot as plt
import pandas as pd


def main():
    data = pd.read_csv('test2.csv', header=None, index_col=0, parse_dates=True)
    data.index.name = 'Zeit'
    data[1].rename('Luftfeuchte aussen').plot(legend=True)
    data[3].rename('Luftfeuchte innen').plot(legend=True)
    plt.show()
    

if __name__ == '__main__':
    main()
Bild
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Mittwoch 15. August 2018, 22:54

Vielen dank für die Antworten.
Hat schon jemand erwähnt, dass Du das csv-Modul benutzen sollst
Ich hab den ganzen oberen Teil mit einem Tutorial gemacht und der hat damit problemlos 4000 spalten aus einer csv Datei ausgewertet.
Benutzeravatar
__blackjack__
User
Beiträge: 1031
Registriert: Samstag 2. Juni 2018, 10:21

Mittwoch 15. August 2018, 23:07

Falls die ``for``-Schleife mit dem `range()` auch aus dem Tutorial stammt, dann taugt das nix. Egal was der Rechner schafft, das ist kein idiomatisches Python. Und das mit dem ``split('\n')`` macht Probleme wenn jede Zeile mit einem Zeilenende abgeschlossen ist, denn dann hat man am Ende der Liste einen leeren Eintrag. Das heisst selbst wenn man erst alles einliest, ist `split()` nicht die richtige Methode für den Job.

Und wenn man mit weniger Code und weniger Speicherverbrauch das gleiche erreichen kann, ist es IMHO sinnvoller das auch zu tun.

Dateien die man öffnet, sollte man auch wieder schliessen. Dazu eignet sich die ``with``-Anweisung, damit die Datei auch auf jeden Fall geschlossen wird, egal warum der ``with``-Block verlassen wird.
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Donnerstag 16. August 2018, 00:01

Ja du hast wahrscheinlich recht das es so wie in dem Tutorial gemacht wird sehr schlecht ist. Sirius kann man bei deinem plot noch Linien von der Uhrzeit hoch ziehen, da man so wenn das ganze 20 oder mehr Werte sind recht schwer zu erkennen wird welcher Wert zu welcher Uhrzeit gehört?
Benutzeravatar
__blackjack__
User
Beiträge: 1031
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 16. August 2018, 09:25

@Hypec: Man könnte da Linien hochziehen, üblicher wäre aber wohl das Gitter zu aktivieren oder ein Balkendiagramm zu erstellen.
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Donnerstag 16. August 2018, 10:28

Wie kann ich das Gitter aktivieren?
__deets__
User
Beiträge: 3289
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 16. August 2018, 10:51

Indem du in die matplotlib Gallery schaust, dir dort einen Plot raussuchst, der dir gefaellt, und den dazugehoerigen Code anschaust um zu verstehen, was die da gemacht haben.
Benutzeravatar
__blackjack__
User
Beiträge: 1031
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 16. August 2018, 10:52

@Hypec: Schau Dir mal die Tutorials und Beispiele bei Matplotlib an und wenn Du ein Gitter siehst, schau wie's gemacht wird.
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Donnerstag 16. August 2018, 10:53

Oke danke werde ich machen
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Donnerstag 16. August 2018, 12:31

Ich habe es jetzt geschafft mit diesem code ein Gitter darzustellen. Wollte jetzt den plot als png anspeichern, was auch problemlos funktioniert bis auf das in dem Gitter die waagrechten Linien nicht mit auf dem Png angezeigt werden. Weiß jemand woran das liegt und wie ich das beheben kann?

Code: Alles auswählen

import csv
import matplotlib.pyplot as plt

with open('test.csv') as lines:
    reader = csv.reader(lines, delimiter=',')
    tabelle = [
        row[:1] + [float(c) for c in row[1:]]
        for row in reader
    ]

        
    
def luftfeuchte():
    
    time = [zeile[0] for zeile in tabelle]
    luftfeuchtedrin = [zeile[1] for zeile in tabelle]
    luftfeuchteausen = [zeile[3] for zeile in tabelle]

    fig, ax = plt.subplots()
    ax.plot(time, luftfeuchtedrin, label="luftfeuchtedrin")
    ax.plot(time, luftfeuchteausen, label="luftfeuchteausen")
    ax.grid(True)
    ax.legend()
    ax.set_title('Luftfeuchte')
    ax.set_ylabel('Luftfeuchtigkeit in %')
    ax.set_xlabel('Uhrzeit')

    fig.show()
Code Plot als Bild speichern:

Code: Alles auswählen

import csv
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
#from matplotlib.figure import Figure

with open('test.csv') as lines:
    reader = csv.reader(lines, delimiter=',')
    tabelle = [
        row[:1] + [float(c) for c in row[1:]]
        for row in reader
    ]

def luftfeuchte():

    time = [zeile[0] for zeile in tabelle]
    luftfeuchtedrin = [zeile[1] for zeile in tabelle]
    luftfeuchteausen = [zeile[3] for zeile in tabelle]
    
    fig, ax = plt.subplots()
    ax.plot(time, luftfeuchtedrin, label="luftfeuchtedrin")
    ax.plot(time, luftfeuchteausen, label="luftfeuchteausen")
    ax.grid(True)
    ax.legend()
    ax.set_title('Luftfeuchte')
    ax.set_ylabel('Luftfeuchtigkeit in %')
    ax.set_xlabel('Uhrzeit')

 
    FigureCanvasAgg(fig).print_png('luftfeuchte.png', dpi=50000)


luftfeuchte()
Benutzeravatar
__blackjack__
User
Beiträge: 1031
Registriert: Samstag 2. Juni 2018, 10:21

Donnerstag 16. August 2018, 12:40

Also bei mir funktioniert das nicht weil `time` keine Zahlen enthält (ValueError: invalid literal for float(): 2018-08-13 14:00:00).

Warum nicht `plt.savefig()`? Und die DPI-Angabe ist *viel* zu hoch. Da möchtest Du vieleicht lieber die Grösse der Abbildung grösser und dafür die DPI-Zahl kleiner wählen. Die DPI-Angabe kann in PNG gespeichert werden, und so etwas unrealistisch grosses macht dann bei der Weiterverarbeitung sicher irgendwo Probleme.
“Capitalism is the astounding belief that the most wickedest of men will do the most wickedest of things for the greatest good of everyone.” – John Maynard Keynes
Hypec
User
Beiträge: 68
Registriert: Mittwoch 1. August 2018, 16:11

Donnerstag 16. August 2018, 15:02

Was wäre eine angemessene dpi Zahl?
__deets__
User
Beiträge: 3289
Registriert: Mittwoch 14. Oktober 2015, 14:29

Donnerstag 16. August 2018, 15:37

Probier es doch aus. Was fuer DPI hat denn dein Monitor? Oder fang an, einfach mal 0en wegzulassen, bis du zB dein Ergebnis mit den gewuenschten waagerechten Linien bekommst. Du musst mal ein bisschen experimentierfreudiger werden, und Dinge ausprobieren und selbst loesen, statt wirklich bei jedem Schritt hier 3 Threads aufzumachen. Denn auf Dauer wird das nicht funktionieren.
Antworten