Seite 1 von 1

Tageshöchstwerte aus csv Datei selektieren

Verfasst: Sonntag 10. März 2024, 20:11
von Schlangenmensch
Hallo,

ich versuche nun schon seit einiger Zeit die Tageshöchstwerte aus einer csv Datei zu selektieren. In der Datei sind täglich im 10 Minuten Abstand Temperaturwerte geloggt.

Beispiel:

11/10/2023;9:59;24.4
11/10/2023;10:9;28.3
11/10/2023;10:119;60.2
11/10/2023;10:29;80.2
" " " " " "


Bis jetzt konnte ich wenigsten einmal nur die Temperaturwerte selektieren. Was kann ich tun um jeweils den höchsten Wert pro Tag anzeigen zu lassen. Ich komme hier leider nicht weiter und hoffe Ihr könnt mir helfen.

Code: Alles auswählen

import os
import csv

with open("/home/****/******/*****.csv","r") as csv_datei:
    reader = csv.reader(csv_datei, delimiter=';')

    for zeile in reader:
        print(zeile[3])

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Sonntag 10. März 2024, 20:27
von __deets__
Pandas benutzen und mal in dessen Dokumentation nach Gruppierung und Maximalwerten schauen, ist alles dokumentiert.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Sonntag 10. März 2024, 20:40
von Sirius3
Dafür gibt es `itertools.groupby`; einfach nach dem Datum gruppieren und per `max` das Maximum suchen.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Sonntag 10. März 2024, 20:43
von noisefloor
Hallo,

CSV ist halt nur ein einfaches, text-basiertes Dateiformat, was per Konvention einer bestimmten Struktur folgt.

Alternativ zu Pandas könntest du auch z.B. https://github.com/wireservice/csvkit/ nutzen.

Gruß, noisefloor

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 11. März 2024, 09:32
von Schlangenmensch
Vielen Dank für Euere Antworten. Da werde ich mich jetzt erst einmal in Pandas einlesen.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 11. März 2024, 10:16
von DeaD_EyE
Du machst den Fehler, den alle Anfänger machen und lernst wie Pandas funktioniert, anstatt erstmal Python zu lernen.
itertools.groupby wäre die einfache Lösung gewesen.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 11. März 2024, 10:51
von __deets__
@DeaD_Eye: warum ist das ein Fehler? Und darf man csv verwenden, oder muss man auch lernen, wie man zeilenweise Dateien einliest? Und die ganzen Typkonvertierungen machen's auch nicht einfacher.

Man muss Grundlagen der Sprache beherschen, das sehe ich auch so. Aber warum man auf das schweizer Taschenmesser verzichten soll, wenn Python ansonsten auch dafuer gelobt wird, so viel Dinge einfach zu machen, ist nicht schluessig in meinen Augen.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 11. März 2024, 12:52
von DeaD_EyE
Es geht nicht darum, keine Bibliotheken zu verwenden, sondern erstmal zu lernen, wie man mit Python programmiert.
Das bedeutet nicht, dass man jede Funktion/Methode einer Bibliothek verstehen muss, aber man sollte schon ungefähr wissen, was im Hintergrund passiert.
Wenn man das nicht weiß, landet man hier im Forum und stellt Fragen.

Und darf man csv verwenden, oder muss man auch lernen, wie man zeilenweise Dateien einliest
  1. Lernen, wie man Zeilenweise einliest
  2. das csv Modul verwenden
  3. dann Pandas
Pandas ist ein eigenes Schweizer Taschenmesser, dass man verstehen muss, um es richtig anzuwenden.

Anfänger will Python lernen und das Erste, was er macht, ist dann ein Pandas-Tutorial. Also lernt der Anfänger Pandas und kein Python.
So lernen die Anfänger brav, wie man Pandas anwenden, scheitern aber schon bei den einfachsten Python-Basics.
Das ist meine Beobachtung über die Jahre und sie bestätigt sich immer wieder.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 11. März 2024, 14:37
von __blackjack__
@Schlangenmensch: ``zeile[3]`` passt nicht zu den gezeigten Daten.

Hier mal eine Möglichkeit das mit Bordmitteln zu lösen:

Code: Alles auswählen

#!/usr/bin/env python3
import csv
from datetime import datetime as DateTime
from itertools import groupby
from operator import itemgetter


def main():
    with open(
        "/home/****/******/*****.csv", "r", newline="", encoding="utf-8"
    ) as csv_file:
        print(
            [
                (
                    #
                    # TODO: Eventuell muss man hier das Datumsformat anpassen,
                    #   da aus dem Beispiel nicht klar wird in welcher
                    #   Reihenfolge Tag und Monat in der Datei angegeben sind.
                    #
                    DateTime.strptime(date_text, "%d.%m.%Y").date(),
                    max(float(row[2]) for row in group),
                )
                for date_text, group in groupby(
                    csv.reader(csv_file, delimiter=";"), itemgetter(0)
                )
            ]
        )


if __name__ == "__main__":
    main()
Falls das erzeugen der Eingabedatei in Deiner Hand liegt: Datum und Zeit ergeben zusammen *einen* Wert, der nicht auf zweit Spalten verteilt werden sollte. Dann müsste man früher in ein `datetime`-Objekt umwandeln und die `key`-Funktion für `groupby()` anpassen. Wäre aber sowieso etwas sauberer die Umwandlung in die passenden Datentypen als *ersten* Schritt zu machen, bevor man die Daten weiterverarbeitet.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Freitag 15. März 2024, 09:27
von Schlangenmensch
Hallo, ich bin hier nur zufällig vorbeigekommen und habe gesehen, es sind noch weitere Lösungsvorschläge eingegangen wofür ich mich hiermit recht herzlich bedanken möchte.

Bisher bin ich mit pandas zumindest schonmal soweit, daß ich bestimmte Einträge selektieren kann. Mir fehlt nun nur noch die tagweise Gruppierung bestimmter Werte.

Ich werde wohl erstmal das ganze versuchen mit pandas zu ende zu bringen um mich danach mit den anderen Lösungsvorschlägen zu beschäftigen.

Das ganze wird noch etwas dauern, da ich nur begrenzt Zeit habe.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 15. April 2024, 13:16
von Schlangenmensch
Hallo allerseits,

ich habe mal wieder etwas Zeit gefunden um an meinem bzw. Euerem Projekt herumzubasteln.

Ich habe Datum und Zeit in "Excel" in einer Spalte zusammengefügt.

Nun habe ich aber das Problem, das ich diese Daten nicht in ein datetime Objekt umwandeln kann, da ich durch csv.reader die Daten in einer Liste vorliegen habe. Ich scheitere daran diese Liste in ein datetime Objekt zu verwandeln.

Hat jemand einen Tip für mich?

Code: Alles auswählen

def main():
    with open(
        "/home/bunjul/Schreibtisch/Lösch.csv", "r", newline="", encoding="utf-8"
    ) as csv_file:
    
    read = csv.reader(csv_file)
    for line in read:
        print(line)
    
       
    
        print(
            [
                (
                    #
                    # TODO: Eventuell muss man hier das Datumsformat anpassen,
                    #   da aus dem Beispiel nicht klar wird in welcher
                    #   Reihenfolge Tag und Monat in der Datei angegeben sind.
                    #
                    DateTime.strptime(date_text, "%d.%m.%Y").date(),
                    max(float(row[1]) for row in group),
                )

                for date_text, group in groupby(
                    csv.reader(csv_file, delimiter=";"), itemgetter(0)
                )
            ]
        )


if __name__ == "__main__":
    main()

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 15. April 2024, 16:06
von Sirius3
Dein Programm funktioniert nicht, weil es falsch eingerückt ist. Und daher kann man auch nicht sehen, was wohin gehört.
Wie sehen Deine Input-Daten aus, und wie die Fehlermeldung, die Du erhältst?

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 15. April 2024, 16:57
von Schlangenmensch
Sorry, da gat mir irgendwas die Formatierung zerschossen.

Im Prinzip gabe ich das Programm von blackjack genommen und wollte dies Erweitern.

Ich lese eine csv datei in folgendem Format ein 02.03.2023 22:30 ; 22,9
02.03.2023 23:50 ;34,5
" " " "

Diese Werte werden, wenn ich das richtig verstanden habe, in einer Liste gespeichert.

Aus dieser Liste möchte ich wie von blackjackbeschrieben ein datetime Objekt machen. Nun weis ich aber nicht wie ich den Datumsstring der Liste in ein datetime Objekt umwandeln kann.

Leider kann ich mlmentan keine Fehlermeldungen posten, da ich unterwegs bin und keine Möglichkeit habe auf eine Konsole bzw. das Programm zuzugreifen. Ich werde die Meldungen bei Gelegenheit posten.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Montag 15. April 2024, 17:09
von __blackjack__
Das `groupby()` funktioniert natürlich nicht mehr einfach durch den Wert in der ersten Spalte wenn der nicht mehr nur das Datum sondern den kompletten Zeitstempel enthält. Statt ``itemgetter(0)`` muss da etwas stehen das von dem Wert in der ersten Spalte das Datum abfragt. Also beispielsweise in dem man den kompletten Zeitstempel in ein `datetime`-Objekt parst und darauf dann `date()` aufruft.

Man könnte auch der Versuchung erliegen und das über Zeichenkettenoperationen zu machen, aber ich mag den Weg über `datetime` lieber, weil da dann auch gleich eine gewisse Validierung erfolgt ob die Daten valide Zeitpunkte sind.

Einen `reader` `read` zu nennen ist komisch und eine Tabellenzeile heisst im Englischen `row` und nicht `line`. Die Schleife ist aber sowieso falsch, denn man will das ja nicht pro Zeile machen, beziehungsweise passiert das ja nur für die erste Zeile weil alle anderen durch den zweiten `reader` *in* der Schleife ja schon verarbeitet wird. Im Moment wird durch dieses wirre Konstrukt die erste Zeile ausgegeben und im weiteren nicht berücksichtigt. Sollte das Absicht sein, beispielsweise weil das eine Kopfzeile ist, dann macht man das nicht *so*, sondern einfach mit einem `next()` auf den *einen* `reader` den man erstellt, bevor man den restlichen Inhalt verarbeitet.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Dienstag 16. April 2024, 02:10
von snafu
Ich find's schon etwas fies, einem Anfänger ein derart verschachteltes Konstrukt vor die Nase zu setzen und dann, wenn er es (erwartungsgemäß) nicht versteht, etwas von wirrem Code zu erzählen. Die LC sollte man IMHO mit zwei Hilfsfunktionen implementieren, damit sie anschließend für den Leser verständlicher wird. Also ich blicke da schon noch durch und viele Regulars bestimmt auch, nur halte ich das nicht für einen wirklich gelungenen Code. Das kannst du eigentlich besser, __blackjack__. :)

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Dienstag 16. April 2024, 08:42
von __blackjack__
@snafu: Diese äussere Schleife über alle Datensätze scheint einzig und alleine dazu da zu sein den ersten Datensatz zu ignorieren. Das ist ja unabhängig davon wie (un)verständlich der Code *in* der Schleife ist, der *tatsächlich* alle Datensätze verarbeitet (bis auf den ersten). Ich finde das extrem verwirrend, denn ``for datensatz in datensätze:`` vermittelt den Eindruck die Schleife sei dazu da alle Datensätze zu behandeln und nicht nur um den *ersten* zu behandeln.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import csv
from collections import namedtuple
from datetime import datetime as DateTime
from itertools import groupby
from operator import attrgetter


class Record(namedtuple("_Record", "timestamp temperature")):

    @property
    def date(self):
        return self.timestamp.date()

    @classmethod
    def from_row(cls, row):
        return cls(
            DateTime.strptime(row[0], "%d.%m.%Y %H:%M"),
            float(row[1].replace(",", ".")),
        )


def main():
    with open(
        "/home/bunjul/Schreibtisch/Lösch.csv", newline="", encoding="utf-8"
    ) as csv_file:
        rows = csv.reader(csv_file, delimiter=";")
        print(next(rows))  # Skip and print header.
        records = map(Record.from_row, rows)
        daily_max_temperatures = (
            max(group, key=attrgetter("temperature"))
            for _, group in groupby(records, attrgetter("date"))
        )
        print(list(daily_max_temperatures))


if __name__ == "__main__":
    main()

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Dienstag 16. April 2024, 15:45
von snafu
__blackjack__ hat geschrieben: Dienstag 16. April 2024, 08:42 @snafu: Diese äussere Schleife über alle Datensätze scheint einzig und alleine dazu da zu sein den ersten Datensatz zu ignorieren.
Ich unterstelle mal, dass hier mehr Glück als Verstand dabei war. Wirklich durchschaut haben wird der TE deinen Ansatz wohl eher nicht.

Das zweite Snippet mit dem "namedtuple" befindet der Rat der Snafus übrigens als deutlich gelungener. Wir haben unsere Sitzung gerade beendet. :D

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Donnerstag 18. April 2024, 18:35
von Schlangenmensch
Hallo allerseits,

ich glaube ich habe die letzte Version des Programmes einigermassen verstanden.

Nun versuche ich noch etwas an der Ausgabe bzw. an der Formatierung herumzubasteln.

Da die Ausgabe der in einer Liste erfolgt, die nicht Zeilenweise ist habe ich mal versucht die Werte zeilenweise zu gliedern. Gibt bestimmt schönere Lösungen. :oops:

Code: Alles auswählen

import csv
from collections import namedtuple
from datetime import datetime as DateTime
from itertools import groupby
from operator import attrgetter


class Record(namedtuple("_Record", "timestamp temperature")):

    @property
    def date(self):
        return self.timestamp.date()

    @classmethod
    def from_row(cls, row):
        return cls(
            DateTime.strptime(row[0], "%d.%m.%Y %H:%M"),
            float(row[1].replace(",", "." )),

        )


def main():
    with open(
        "/home/bunjul/Schreibtisch/Lösch.csv", newline="", encoding="utf-8"
    ) as csv_file:
        rows = csv.reader(csv_file, delimiter=";")
        print(next(rows))  # Skip and print header.
        records = map(Record.from_row, rows)
        daily_max_temperatures = (
            max(group, key=attrgetter("temperature"))
            for _, group in groupby(records, attrgetter("date"))
        )
        

        x =  (list(daily_max_temperatures))
        for l in x:

            print(l)
            




if __name__ == "__main__":
    main()


Des Weiteren würde ich die "Listenausgabe":

Record(timestamp=datetime.datetime(2023, 1, 2, 16, 33), temperature=88.1)
Record(timestamp=datetime.datetime(2023, 3, 5, 1, 44), temperature=55.4)
Record(timestamp=datetime.datetime(2023, 4, 5, 5, 22), temperature=22.5)
Record(timestamp=datetime.datetime(2023, 5, 5, 10, 22), temperature=33.4)

wie folgt formatieren: 22.12.2023 16:33 , 44.5

Leider fehlt mir hierzu schlichtweg das Wissen, wie ich diese Formatierung umsetzen kann.

Gerne bin ich auch bereit eine kleine Spende zu überweisen, wenn mir jemand die Formatierung schreibt.

Re: Tageshöchstwerte aus csv Datei selektieren

Verfasst: Donnerstag 18. April 2024, 19:25
von Sirius3
`l` ist der schlechteste Variablennamen, den es überhaupt gibt, nicht nur, dass der nichtssagend ist, sondern auch noch, dass man den leicht mit 1 oder I verwechseln kann.
`x` ist auch nicht viel besser für eine Liste.
Für die Ausgabe benutzt man f-Strings:

Code: Alles auswählen

for daily_max_temperature in daily_max_temperatures:
    print(f"{daily_max_temperature.timestamp:%d.%m.%Y %H:%M}, {daily_max_temperature.temperature:.1f}")