2 mal das Datum abfragen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Hallo,
ich will das der Benutzer ein Startdatum eingibt und ein Enddatum um ihm die dazwischenliegenden Messdaten aus einer csv Datei anzeigen zu können.
Die Csv Datei sieht so aus(natürlich dann mit der Zeit mit mehr messwerten):

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
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Schön, dass du das willst. Kommt dazu noch eine Frage, oder wolltest du das nur mitteilen?
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Die Frage ist vermutlich wie es funktioniert. Ich würde hier das pandas-Modul benutzen. Damit ist es mit wenigen Zeilen erledigt:

Code: Alles auswählen

from datetime import time
from io import StringIO
import pandas as pd

TEST_CSV = u"""2018-08-16 14:00:00,71.60,22.20,53.10,22.50,834,225.00
2018-08-16 15:00:00,60.40,23.40,54.20,23.40,830,230.00
2018-08-16 16:00:00,64.30,21.30,53.60,24.30,835,231.67
2018-08-16 17:00:00,62.50,26.90,59.50,26.90,829,742.75
2018-08-16 18:00:00,71.60,18.80,57.30,21.20,827,3643.33
2018-08-16 19:00:00,60.40,22.60,56.90,22.50,833,4084.17
2018-08-16 20:00:00,64.30,25.50,56.80,26.90,826,4517.17
2018-08-16 21:00:00,62.50,26.90,64.60,23.40,840,4342.92"""

def select_by_time(csv, start, end):
    df = pd.read_csv(StringIO(csv), header=None, index_col=0, parse_dates=True)
    return df[time(*start):time(*end)]

def main():
    result = select_by_time(TEST_CSV, (15, 0), (19, 0))
    print(result)

if __name__ == '__main__':
    main()
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

snafu danke erstmal für die Lösung und ja es sollte die Frage sein wie es funktioniert. Kann man oben bei dem TEST_CSV die Datei nicht automatisch einlesen lassen da es bei 1000 oder mehr zeilen vermutlich mit der Methode nicht mehr so produktiv ist. Ich hab hier auch noch ein Script wo die Daten alle eingelesen werden und dann als in einem Plot dargestellt werden.

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()
    fig.show()

def temperatur():
    time = [zeile[0] for zeile in tabelle]
    tempraturdrin = [zeile[2] for zeile in tabelle]
    temperaturausen = [zeile[4] for zeile in tabelle]

    fig, ax = plt.subplots()
    ax.plot(time, tempraturdrin, label="temperaturdrin")
    ax.plot(time, temperaturausen, label="tamperaturausen")
    ax.grid(True)
    ax.legend()
    fig.show()

def erdfeuchte():
    time = [zeile[0] for zeile in tabelle]
    erdfeuchte = [zeile[5] for zeile in tabelle]

    fig, ax = plt.subplots()
    ax.plot(time, erdfeuchte, label="erdfeuchte")
    ax.grid(True)
    ax.legend()
    fig.show()

def lux():
    time = [zeile[0] for zeile in tabelle]
    lux = [zeile[6] for zeile in tabelle]

    fig, ax = plt.subplots()
    ax.plot(time, lux, label="lichtitensität(lux)")
    ax.grid(True)
    fig.legend()
    fig.show()
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Das kann man, indem man die Grundlagen von Python lernt und sich zumindest mit der Doku von read_csv() beschäftigt. Dann erfährt man, dass man jedes Objekt mit einer read()-Methode (also natürlich auch "echte" Dateiobjekte) oder einfach den gewünschten Dateinamen übergeben kann. Das mit dem StringIO() war ja nur zum Testen gedacht.

Der von dir gezeigte Code geht ja gar nicht nach dem Datum. Hierdurch weiß ich leider nicht, was dein eigentliches Ziel ist: Daten nach Uhrzeit/Datum herausfiltern oder nun doch händisch nach dem Index vorgehen?

Ich kann nur sagen, dass read_csv() sehr mächtig ist, auch wenn man sich da erstmal einlesen muss. Statt der nachträglichen List Comprehensions könntest du besser mittels usecols direkt sagen, welche Spalten benötigt werden.
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Oke dann lese ich mich mal tiefer über read_csv() ein. Mein Code soll am ende wenn er fertig ist dafür da sein das man einen Zeitraum auswählt und dann anschließend welche Messdaten man aus diesem Zeitraum angezeigt bekommen möchte.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ich würde es so machen, dass Zeile für Zeile in einer Processing-Pipeline durchläuft. Man kann Generatoren auch verketten.
Das heißt ganz am Anfang hast du deinen csv_reader Objekt dessen Zeilen nach Datum gefiltert werden.
Als Generator könnte das so aussehen:

Code: Alles auswählen

def filter_by_date(csv_reader, start_dt, end_dt):
    dt_fmt = '%Y-%m-%d %H:%M:%S' 
    for row in csv_reader:
        dt_from_csv = row[0]
        dt_from_csv = datetime.datetime.strptime(dt_from_csv, dt_fmt)
        if dt_from_csv > end_dt:
            break
        if dt_from_csv > start_dt:
            yield row
Die Iteration wird beendet, sobald das Enddatum größer ist als das Datum in der CSV-Datei.
Solange start_dt größer als die gelesene Zeit ist, wird nichts ausgegeben.

Kann man auch alles mit Pandas machen, aber dann weißt du halt nur wie man Pandas benutzt.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@DeaD_EyE: wenn Du schon schreibst, dass man Generatoren verketten kann, warum nennst Du dann den ersten Parameter, der irgendein Iterator sein kann `csv_reader`? Die kryptischen Prä- und Postfixe `dt` sind allesamt unnötig. Gegenüber allen üblichen Konventionen, den Start inklusive und das Ende exklusive zu sehen, hast Du es genau umgedreht.

Code: Alles auswählen

def filter_by_date(iterable, start, end, format= '%Y-%m-%d %H:%M:%S'):
    for row in iterable:
        timestamp = datetime.datetime.strptime(row[0], format)
        if timestamp >= end:
            break
        elif timestamp >= start:
            yield row
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Ganz einfach: Damit du wieder was zum rumkacken hast.
Du bist mir jetzt schon mehrere male ziemlich negativ aufgefallen.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Hallo kann mir jemand sagen was an diesem Script falsch ist, das ich nachdem ich die beiden Variabeln start und end eingegeben habe diese Fehlermeldung bekomme?

Code: Alles auswählen

from datetime import time
from io import StringIO
import pandas as pd
import csv

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 select_by_time(csv, start, end):
    df = pd.read_csv(StringIO(csv), header=None, index_col=0, parse_dates=True)
    return df[time(*start):time(*end)]

def main():
     
    time = [zeile[0] for zeile in tabelle ]
    str_tabelle = " ".join(time)
    start = int(input("Ihre Eingabe start? "))
    end = int(input("Ihre Eingabe end? "))
    result = select_by_time(str_tabelle, (start, 0), (end, 0))
    print(result)

if __name__ == '__main__':
    main()

Code: Alles auswählen

Ihre Eingabe start? 15
Ihre Eingabe end? 17
Traceback (most recent call last):
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 3078, in get_loc
    return self._engine.get_loc(key)
  File "pandas\_libs\index.pyx", line 140, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\_libs\index.pyx", line 162, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\_libs\hashtable_class_helper.pxi", line 1492, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas\_libs\hashtable_class_helper.pxi", line 1500, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: datetime.time(15, 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4238, in get_slice_bound
    slc = self._get_loc_only_exact_matches(label)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4207, in _get_loc_only_exact_matches
    return self.get_loc(key)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 3080, in get_loc
    return self._engine.get_loc(self._maybe_cast_indexer(key))
  File "pandas\_libs\index.pyx", line 140, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\_libs\index.pyx", line 162, in pandas._libs.index.IndexEngine.get_loc
  File "pandas\_libs\hashtable_class_helper.pxi", line 1492, in pandas._libs.hashtable.PyObjectHashTable.get_item
  File "pandas\_libs\hashtable_class_helper.pxi", line 1500, in pandas._libs.hashtable.PyObjectHashTable.get_item
KeyError: datetime.time(15, 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/Programmieren/Python/Dateien/Csv Lesen/Eingabe_1.py", line 27, in <module>
    main()
  File "D:/Programmieren/Python/Dateien/Csv Lesen/Eingabe_1.py", line 23, in main
    result = select_by_time(str_tabelle, (start, 0), (end, 0))
  File "D:/Programmieren/Python/Dateien/Csv Lesen/Eingabe_1.py", line 15, in select_by_time
    return df[time(*start):time(*end)]
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\frame.py", line 2676, in __getitem__
    indexer = convert_to_index_sliceable(self, key)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexing.py", line 2326, in convert_to_index_sliceable
    return idx._convert_slice_indexer(key, kind='getitem')
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 1751, in _convert_slice_indexer
    indexer = self.slice_indexer(start, stop, step, kind=kind)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4107, in slice_indexer
    kind=kind)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4308, in slice_locs
    start_slice = self.get_slice_bound(start, 'left', kind)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4241, in get_slice_bound
    return self._searchsorted_monotonic(label, side)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\indexes\base.py", line 4191, in _searchsorted_monotonic
    return self.searchsorted(label, side=side)
  File "D:\Programmieren\Python\lib\site-packages\pandas\util\_decorators.py", line 178, in wrapper
    return func(*args, **kwargs)
  File "D:\Programmieren\Python\lib\site-packages\pandas\core\base.py", line 1230, in searchsorted
    return self.values.searchsorted(value, side=side, sorter=sorter)
TypeError: '<' not supported between instances of 'str' and 'datetime.time'
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Welche Spalte in deinem Dataframe willst du denn hiermit adressieren?

Code: Alles auswählen

return df[time(*start):time(*end)]
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
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Die spalte wo das Datum und die uhrzeit drin stehen.
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

dann lass dir doch mal df.columns.values ausgeben und überprüfe ob time(*start):time(*end) einem der Einträge irgendwie nahe kommt
PS: man adressiert eine Spalte in einem Dataframe z.B. so df['Name']
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
Hypec
User
Beiträge: 183
Registriert: Mittwoch 1. August 2018, 16:11

Was ich vergessen habe zu schreiben ist das wenn ich bei der Zeile das Leerzeichen zwischen den Anführungszeichen weg lasse ich dieses Ergebnis bekomme.

Code: Alles auswählen

    str_tabelle = " ".join(time)

Code: Alles auswählen

Ihre Eingabe start? 15
Ihre Eingabe end? 17
Empty DataFrame
Columns: []
Index: []
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hypec: arbeite man ein Tutorial zu Python und Pandas durch. Blind Code zusammen zu kopieren wird die, wie Du anscheinend selbst gerade merkst, nicht zu einer Lösung führen. Du hast Teile meiner Lösung, die ohne Pandas arbeitet mit der von snafu kombiniert, ohne sie wirklich verstanden zu haben. snafu hat StringIO benutzt, um ein lauffähiges Beispiel zu haben, Du brauchst das aber nicht, weil Du die Datei direkt lesen kannst, ohne csv.reader.

Code: Alles auswählen

from datetime import time
import pandas as pd

def select_by_time(filename, start, end):
    df = pd.read_csv(filename, header=None, index_col=0, parse_dates=True)
    return df[time(*start):time(*end)]

def main():
    start = int(input("Ihre Eingabe start? "))
    end = int(input("Ihre Eingabe end? "))
    result = select_by_time("test.csv", (start, 0), (end, 0))
    print(result)

if __name__ == '__main__':
    main()
Antworten