Matplotlib Render Zeit

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

Servus,

dies ist mein erster Post in diesem Forum und ich hoffe mal, dass ich nichts Falsch mache und mich verständlich ausdrücke, da ich kein Programmiere von Haus aus bin :D :D :D .

Das Problem:
Die Renderzeit von meinem Plot den ich mit matplotlib generiere braucht ca. 120 sec und wird dann Nichtmal richtig erstellt. Es sieht so aus als ob sich Plots "überlagern" ist schwierig zu erklären. Ich würde gerne ein Bild dazu teilen was aber glaub nicht über das Forum geht oder?

Ich habe schon viel gesucht und leider nichts konkretes gefunden. Wahrscheinlich ist es irgendeine Kleinigkeit die ich übersehen habe. :?: :?: :?: :?:

Die hardware:
i5 quadcore 2.71ghz 8gb ram + halb leere ssd
2. System auf dem ich den code ausprobiert habe war um einiges stärke hat aber auch nicht wirklich funktioniert

Quellcode: (Code Editor Atom, Ausführung über das paket script von rgbkrk, habe aber das ganze auch schon via VS Code probiert und kam zum selben Ergebniss.)

Code: Alles auswählen

import numpy
import pandas as pd
import matplotlib.pyplot as plt
import csv

###Festlegen Welcher File Importiert wird. ## Muster file: NDAc_0810_no_salt.csv
url = 'ExcelFiles/NDAc_0810_no_salt.csv' ###Needs String


###Functions###
def getData(url): # Import Data and prepare them
    data = []

    with open (url, 'r') as file:
        for line in file:
            dataLine = line.strip().split(';')
            data.append(dataLine)
    return data

zeit = []
pH  = []
vol = []
conduct = []
turb = []

def sortData(unSortedData): #Sort Data to List Object
    i = 0
    for line in unSortedData:
        i = i + 1
        if i == 1:
            continue
        dataLine = line
        zeit.append(dataLine[0])
        pH.append(dataLine[1])
        vol.append(dataLine[2])
        conduct.append(dataLine[5])
        turb.append(dataLine[6])
    sortedData = {'Zeit': zeit,'pH': pH,'Volumen': vol,'Leitfaehigkeit': conduct,'Turbidity': turb}
    return sortedData


### prepare Data for Plotting ###

unSortedData = getData(url)
sortedData = sortData(unSortedData)
#print(sortedData)

df = pd.DataFrame(sortedData)

print(df) ### Print data for check





### Plot data ###

plt.plot(zeit,pH)
plt.xlabel('Test')
plt.ylabel('test2')
plt.show()
Der Code ist definitiv nicht perfekt aber das ist das beste was ich bisher hin bekomme und bin natürlich auch für Semantische Tipps offen, aber Hauptsächlich geht es mir darum das mein Plot nun richtig generiert wird und zu verstehen warum er gerade nicht richtig generiert wird.

Mein Datensatz sieht Schematisch so aus:
Ich wäre auch bereit den zu teilen, dies geht aber glaub nicht über das Forum oder?


Nr. Zeit pH Volumen Leitfaehigkeit Turbidity
0 0 11.25 0 2.9723 168.4
1 2 11.23 0 2.9772 168.4
2 4 11.245 0 2.9589 168.6
3 6 11.244 0 2.9726 168.8
4 8 11.257 0 2.9691 168.4
... ... ... ... ... ...
3780 7559.25 2.188 5.162 10.7558 1.6
3781 7561.25 2.188 5.164 10.7659 1.6
3782 7563.25 2.187 5.168 10.7771 1.6
3783 7565.25 2.187 5.172 10.7857 1.6
3784 7566.05 2.187 5.172 10.7878 1.6
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Der Code sieht viel komplizierter aus, als er sein müßte. Vor allem die globalen Listen. Das kann, wenn ›sortData‹ öfter aufgerufen wird, zu komischen Ergebnissen führen. Da wir aber nicht wissen, was Du mit „überlagert” meinst, ohne die kompletten Daten zu haben, kann man Dir nicht helfen.

Das ganze läßt sich in drei Zeilen schreiben:

Code: Alles auswählen

import pandas as pd
import matplotlib.pyplot as plt

filename = 'ExcelFiles/NDAc_0810_no_salt.csv' 
df = pd.read_csv(filename, delimiter=';')
plt.plot(df['Zeit'], df['pH'])
plt.show()
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

Man Oh man, da habe ich mich ganzschön dämlich angestellt. Manchmal kann es so einfach sein. vielen Dank für deine schnelle Hilfe.

Ich verstehe trotzdem nicht warum mein code nicht funktioniert.
Nochmal vielen Dank!
Sirius3 hat geschrieben: Montag 28. Oktober 2019, 19:05 Der Code sieht viel komplizierter aus, als er sein müßte. Vor allem die globalen Listen. Das kann, wenn ›sortData‹ öfter aufgerufen wird, zu komischen Ergebnissen führen. Da wir aber nicht wissen, was Du mit „überlagert” meinst, ohne die kompletten Daten zu haben, kann man Dir nicht helfen.

Das ganze läßt sich in drei Zeilen schreiben:

Code: Alles auswählen

import pandas as pd
import matplotlib.pyplot as plt

filename = 'ExcelFiles/NDAc_0810_no_salt.csv' 
df = pd.read_csv(filename, delimiter=';')
plt.plot(df['Zeit'], df['pH'])
plt.show()
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Snake_py: Aus Deinem Code kann man als erstes mal Sachen entfernen die am Ende gar nicht zum Plot beitragen. Das wäre `pandas` und der `DataFrame`. Wenn man dann noch die globalen Variablen lokal macht und sich an die Konventionen bei der Namenschreibweise in Python hält, sieht das so aus:

Code: Alles auswählen

#!/usr/bin/env python3
from matplotlib import pyplot as plt

DATA_FILENAME = "ExcelFiles/NDAc_0810_no_salt.csv"


def get_data(url):
    data = []
    with open(url, "r") as file:
        for line in file:
            data_line = line.strip().split(";")
            data.append(data_line)
    return data


def sort_data(unsorted_data):
    zeit = []
    ph = []
    vol = []
    conduct = []
    turb = []
    i = 0
    for line in unsorted_data:
        i = i + 1
        if i == 1:
            continue
        data_line = line
        zeit.append(data_line[0])
        ph.append(data_line[1])
        vol.append(data_line[2])
        conduct.append(data_line[5])
        turb.append(data_line[6])

    return {
        "Zeit": zeit,
        "pH": ph,
        "Volumen": vol,
        "Leitfaehigkeit": conduct,
        "Turbidity": turb,
    }


def main():
    unsorted_data = get_data(DATA_FILENAME)
    sorted_data = sort_data(unsorted_data)

    plt.plot(sorted_data["Zeit"], sorted_data["pH"])
    plt.xlabel("Test")
    plt.ylabel("test2")
    plt.show()


if __name__ == "__main__":
    main()
„Sort“/„sorted“ wird hier aber falsch oder zumindest irreführend verwendet. Damit verbindet man die Reihenfolge von Daten, nach einen Sortierkriterium, nicht das aufteilen von ”Zeilenlisten” auf ”Spaltenlisten”.

`url` ist ohne Pandas keine URL mehr sondern ein Dateiname.

`getData()` lässt sich mit einer „list comprehension“ kompakter ausdrücken.

Wenn man zusätzlich zu den Elementen aus einem iterierbaren Objekt noch eine fortlaufende Zahl benötigt, nimmt man die `enumerate()`-Funktion, statt so einen Zähler manuell anzulegen und zu erhöhen.

Allerdings ist das hier unnötig umständlich überhaupt einen Zähler zu verwenden nur um das erste Element eines iterierbaren Objekts zu ignorieren. Das löst man einmal *vor* der Schleife, statt *in* der Schleife jedes mal etwas prüfen und aktualisieren zu müssen.

Das umbennenen von `line` in `data_line` macht keinen Sinn. Da kann man die Laufvariable gleich `data_line` nennen. Wobei `line` hier falsch ist. Im Deutschen ist Textzeile und Tabellenzeile beides „Zeile“, im Englischen ist Textzeile `line` und Tabllenzeile `row`.

Zwischenstand (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python3
from matplotlib import pyplot as plt

DATA_FILENAME = "ExcelFiles/NDAc_0810_no_salt.csv"


def get_rows(filename):
    with open(filename, "r", encoding="ascii") as file:
        return [line.strip().split(";") for line in file]


def get_column_name_to_values(rows):
    rows = iter(rows)
    next(rows)  # Ignore headers.
    
    time = []
    ph = []
    volume = []
    conductivity = []
    turbidity = []
    for row in rows:
        time.append(row[0])
        ph.append(row[1])
        volume.append(row[2])
        conductivity.append(row[5])
        turbidity.append(row[6])

    return {
        "Zeit": time,
        "pH": ph,
        "Volumen": volume,
        "Leitfaehigkeit": conductivity,
        "Turbidity": turbidity,
    }


def main():
    rows = get_rows(DATA_FILENAME)
    column_name_to_values = get_column_name_to_values(rows)

    plt.plot(column_name_to_values["Zeit"], column_name_to_values["pH"])
    plt.xlabel("Test")
    plt.ylabel("test2")
    plt.show()


if __name__ == "__main__":
    main()
Warum das nicht funktioniert: Sowohl Zeit- als auch pH-Werte sind keine Zahlen. Die werden also beide für den Plot wie Kategorien interpretiert, was bei einem `plot()` auch nicht wirklich Sinn macht.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

@__blackjack__

Oh wow! Ich war nicht auf eine so ausführliche Antwort gefasst. Den größten teil habe ich verstanden. Vielen Dank dass du dir die Mühe gemacht hast. Es ist einfach echt schwer ohne"Mentor" programmieren ordentlich zu erlernen. Ich verstehe deinen Code sogar viel besser als meinen :D

Auch verstehe ich, dass es sinn macht einen Main zu definieren, aber bin mir nicht so sicher wozu das if statement dadrunter ist?

Die Lösung die vor dir gepostet wurde rennt auch durch, aber muss ehrlich gestehen dass ich bei deinem Post mehr gelernt habe.
Wusste z.B. nicht dass man eine schleife returnen kann :D

Vielen Dank!

Code: Alles auswählen

with open(filename, "r", encoding="ascii") as file:
        return [line.strip().split(";") for line in file]
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Code: Alles auswählen

if __name__ == "__main__":
    main()
ist per Kovention der Standard um eine main-Funktion zu starten.

__name__ beinhaltet den Namen des Moduls. Es sei denn, es handelt sich um das Modul, das initial vom Interpreter gestartet wurde. Dann ist der Inhalt von __name__ "__main__". So kann man feststellen ob das aktuelle Modul das Modul ist, das durch den Interpreter gestartet wurde.

Welchen Vorteil hat das? Alles was sich auf Modulebene befindet, wird ausgeführt, wenn ein Modul importiert wird. Deshalb sollen auf dieser Ebene nur die Definition von Konstanten, Funktionen und Klassen stehen. Dann kannst du es gefahrlos importieren ohne dass versehentlich etwas ausgeführt wird, was du nicht möchtest. Es gibt auch Hilfsprogramme (Tracer oder Programme die Ausführungszeiten messen), in die man aus diesem Grund ein Modul importieren muss. Hält man sich von vornherein an die Konvention hat man nie ein Problem.
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

@sparrow:

Achso ok also man definiert die if Funktion dafür wenn man das script wo anders über den Import befehl importieren möchte? Oder wie meinst du das? :shock: :shock:

Ich meine den Interpreter starte ich doch jedes mal wenn ich das Script einfach ausführe? Ich habe noch nie etwas so Komplexes programmiert wo ich mir eigene Module schreiben musste, wobei ich gerne würde.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Man benutzt sie einfach immer.
Du tust den "Start" deines Programms in die main() Funktion und rufst diese mit dem if __name__ ... Block auf. Für dich macht es faktisch kaum einen Unterschied. Es ist aber sauberer, beugt Fehlern vor und du kommst nicht in Probleme, wenn du dein Programm mal importieren musst.
Wie gesagt: es muss gar nicht sein, dass dein Programm dafür gedacht ist, als Modul importiert zu werden. Es gibt verschiedene Tools, die nur funktionieren wenn du ein Programm dort importierst. Und solltest du einmal ein solches Tool brauchen, wird es einfach funktionieren und du musst nichts umschreiben.

Es gilt: Auf Modulebene (also im Python-Quelltext "ohne Einrückung") werden nur Konstanten, Klassen und Funktionen definiert. Ansonsten sollte dort nichts stehen. Außer natürlich oben die Importe und ganz unten dieses if-Statement zum starten der main()-Funktion.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@sparrow: Wobei die Importe ja nicht gegen die Faustregel sind — die dienen ja auch nur dazu Konstanten, Funktionen, und Klassen zu definieren wenn in den Modulen ebenfalls sauber programmiert wurde. 🙂

@Snake_py: Was man auch bei Programmen die nur aus einem Modul bestehen, schnell mal brauchen kann, ist das importieren dieses Moduls in einer Python-Shell um einzelne Funktionen zu testen um Fehler leichter finden zu können, in dem man die Funktion mal interaktiv mit verschiedenen Werten aufruft um zu schauen wie sie sich verhält. Statt das man dafür immer das gesamte Programm mit verschiedenen Eingabedaten laufen lassen muss. Es ist auch nicht immer so einfach die Daten so aufzubereiten, das an der bestimmten Funktion für die man sich interessiert, dann genau das vorbeikommt was man testen möchte.

Der nächste Schritt in dieser Richtung sind dann Unit-Tests, also Tests die man automatisiert immer wieder gegen den Code laufen lassen kann, den man entwickelt. Um zum Beispiel ausschliessen zu können, dass Code der korrekt ist, bei der Weiterentwicklung wieder kaputt geht.

Analyse- und Dokumentationswerkzeuge wollen Module auch manchmal importieren um dann ihre Arbeit zu erledigen. In der Standardbibliothek gibt es das `multiprocessing`-Modul das zumindest unter Windows nur korrekt funktioniert wenn man das Modul das als Programm ausgeführt wird ohne Seiteneffekte importieren kann.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Snake_py hat geschrieben: Dienstag 29. Oktober 2019, 22:14 Wusste z.B. nicht dass man eine schleife returnen kann :D

Code: Alles auswählen

with open(filename, "r", encoding="ascii") as file:
        return [line.strip().split(";") for line in file]
Da wird keine Schleife zurück gegeben, das " [line.strip().split(";") for line in file] " nennt sich "list comprehension" und ist im Ergebnis eine Liste.
https://docs.python.org/3/tutorial/data ... rehensions
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

Und wie soll ich die dann so aufrufen?

Soll ich am anfang des Scripts dann schreiben:

Code: Alles auswählen

__name__=="__main__"
Oder was verstehe ich falsch? :?: :?:
sparrow hat geschrieben: Mittwoch 30. Oktober 2019, 11:30 Man benutzt sie einfach immer.
Du tust den "Start" deines Programms in die main() Funktion und rufst diese mit dem if __name__ ... Block auf. Für dich macht es faktisch kaum einen Unterschied. Es ist aber sauberer, beugt Fehlern vor und du kommst nicht in Probleme, wenn du dein Programm mal importieren musst.
Wie gesagt: es muss gar nicht sein, dass dein Programm dafür gedacht ist, als Modul importiert zu werden. Es gibt verschiedene Tools, die nur funktionieren wenn du ein Programm dort importierst. Und solltest du einmal ein solches Tool brauchen, wird es einfach funktionieren und du musst nichts umschreiben.

Es gilt: Auf Modulebene (also im Python-Quelltext "ohne Einrückung") werden nur Konstanten, Klassen und Funktionen definiert. Ansonsten sollte dort nichts stehen. Außer natürlich oben die Importe und ganz unten dieses if-Statement zum starten der main()-Funktion.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Snake_py: Ich verstehe die Frage nicht? Die Bedingung steht am Ende, denn damit die `main()`-Funktion aufgerufen werden kann muss sie ja definiert sein, und alles was sie dann verwendet muss auch definiert sein.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

Ok ich habe es gerade ausprobiert, mit dem code woran ich gerade arbeit, welcher übrigens der ist wo wir in dem anderen Thread gesprochen haben und es rennt durch. Aber warum??
__name__ ist doch nicht gleich "__main__" oder? Ich stehe gerade glaub einfach auf dem Schlauch :?: :?: :?: Ich werde nachher mal googlen und mal nach einer guten Nacht Lektüre schauen

Code: Alles auswählen

import pandas as pd

filename = 'ExcelFiles/datenPlateReader/Platereader_testDaten.csv'


def import_data(filename):
    with open (filename, 'r') as file:
            return [row.strip().split(";") for row in file]


def sort_save_data_set(imported_data):
    data_set_list = []
    for data in imported_data:
        if data[0] != "":
            data_set_list.append(list)
        else:
            df = pd.DataFrame(data_set_list)
            df.transpose()
            df.to_csv('C:/Users/vabis/OneDrive/Uni/Semester 3/Vertiefungspraktikum/Python Scripts/ExcelFiles/datenPlateReader/Datensaetz/firstExperiment/A1.csv')

def main(filename):
    imported_data = import_data(filename)
    #print(imported_data[0][0])
    sort_save_data_set(imported_data)

if __name__ == "__main__":
    main(filename)
__blackjack__ hat geschrieben: Mittwoch 30. Oktober 2019, 22:10 @Snake_py: Ich verstehe die Frage nicht? Die Bedingung steht am Ende, denn damit die `main()`-Funktion aufgerufen werden kann muss sie ja definiert sein, und alles was sie dann verwendet muss auch definiert sein.
Benutzeravatar
__blackjack__
User
Beiträge: 13110
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Snake_py: Wenn `main()` aufgerufen wird, dann ist `__name__` ganz offensichtlich gleich "__main__". Kannst es Dir ja auch mit ``print(__name__)`` ausgeben.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Snake_py
User
Beiträge: 23
Registriert: Montag 28. Oktober 2019, 16:29

Gesagt getan. Nnun ergibt es auch irgendwie Sinn. In __name__ ist automatisch der String __main__ honterlegt. :geek:

Vielen Dank :D
__blackjack__ hat geschrieben: Mittwoch 30. Oktober 2019, 23:29 @Snake_py: Wenn `main()` aufgerufen wird, dann ist `__name__` ganz offensichtlich gleich "__main__". Kannst es Dir ja auch mit ``print(__name__)`` ausgeben.
Antworten