asc File Zeilen Suchen und entfernen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Mein Problem besteht darin, dass in einer asc Datei Fehlerhafte Bereiche enthalten sind

Code: Alles auswählen

27.03.2019;17:18:26;000000470.243300;1100001x;800A6AC9;00000008;
27.03.2019;17:18:26;000000470.243600;1100001x;800A6AD0;00000010;
ErrorFrames: 0 4702439 1 0 0 1
27.03.2019;17:18:26;000000470.243900;10008x;00000000;00000000;
27.03.2019;17:18:26;000000470.246200;DD00011x;8002019E;00000088;
ErrorFrames: 0 4702644 1 0 0 2
27.03.2019;17:18:26;000000470.264400;20008x;00000000;00000000;
Jetzt möchte ich gern die asc Datei Zeile für Zeile einlesen und jede Zeile welche "ErrorFrames enthält gar nicht erst in die neue Variable speichern, oder einfach die Zeilen mit "ErrorFrames auszulassen.
Keine Ahnung was hier besser wäre.

Mein Gedanke war jetzt das mit einer for Schleife zu lösen.

Code: Alles auswählen

         df_all = pd.read_csv(self.file_asc)
         for lines in df_all:
            if lines != "ErrorFrames: 0 4702439 1 0 0 1":
               None
            else:
               neue_csv.append(lines)
Aber genaueres kann ich ihm Internet leider nicht finden, zumindest nichts was mein Problem betrifft.
Meine Python Kenntnisse reichen hier noch nicht so weit.

Dieses Video sah zwar vielversprechend aus
https://www.youtube.com/watch?v=2AFGPdN ... 9y&index=8
Aber es dürfte eher zu umständlich sein und konnte es auch nicht zusammenbringen.

Vielleicht hat jemand Erbarmen und Erleuchtet mich :)
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Du mußt die Zeilen vor dem Aufruf von read_csv herausfiltern.

Normalerweise macht man sowas mit einem Iterator.

Code: Alles auswählen

with open(self.file_asc) as lines:
    filtered_lines = (line for line in lines if not line.startswith('ErrorFrame'))
Irgendwie habe ich aber nichts gefunden, dass Pandas auch von Iteratoren lesen kann.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Man könnte das `comment`-Argument zum Filtern dieser Zeilen missbrauchen.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@__blackjack__: das kommt aber nur mit einem Buchstaben klar. Wahrscheinlich kollidiert das, wenn ein `E` in einem der Hex-Werte vorkommt.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Dann würde ich die Zeilen einfach nach dem einlesen herausfiltern. Das ist ja recht deutlich identifizierbar was bei solchen Zeilen in der Datumsspalte landet. Oder man filtert die Datei erst einmal in ein `io.BytesIO`-Objekt und übergibt das dann der `read_csv()`-Funktion.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

wie wäre es hiermit:

Code: Alles auswählen

with open('data.csv') as file:
    skiprows = [i for i, line in enumerate(file) if line.startswith('Error')]

df = pd.read_csv('data.csv', sep=';', skiprows=skiprows)
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
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

Oder so:

Code: Alles auswählen

from functools import partial
from io import StringIO
import pandas as pd

with open('data.csv') as fobj:
    buffer = StringIO('\n'.join(line.strip(';\n') for line in fobj if not line.startswith('ErrorFrame')))

df = pd.read_csv(buffer, sep=';', header=None, converters={4: partial(int, base=16)})
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

kbr hat geschrieben: Freitag 2. August 2019, 19:14 Oder so:

Code: Alles auswählen

from functools import partial
from io import StringIO
import pandas as pd

with open('data.csv') as fobj:
    buffer = StringIO('\n'.join(line.strip(';\n') for line in fobj if not line.startswith('ErrorFrame')))

df = pd.read_csv(buffer, sep=';', header=None, converters={4: partial(int, base=16)})
Danke dein Code hat mir sehr geholfen!
Hab den Code leicht angepasst

Code: Alles auswählen

         with open(self.file_asc) as file:
            buffer = StringIO('\n'.join(line.strip(';\n') for line in file if not line.startswith('ErrorFrames')))
            print(buffer)

         self.df_all = pd.read_csv(buffer, sep = ";", skiprows = 5, skipinitialspace = True, converters = {'DATA L': partial(int, base = 16)})
Damit ist der Montag gerettet :)

Ein kleines Problem wäre da noch und zwar, ich lese eine xml Datei aus und die Werte welche zusammen gehören werden in eine liste gespeichert.
Jetzt möchte ich einen Wert mit der Formel welche in der liste gespeichert ist Berechnen.

Funktioniert:

Code: Alles auswählen

values_Name_1 = df_Name_1["DATA L"].apply(lambda v: v*(5/1024)*9.980487805)
Funktioniert nicht:

Code: Alles auswählen

values_Name_1 = df_Name_1["DATA L"].apply(lambda v: self.liste[0][1])
Liegt daran dass es als str gepeichert wird und wegen dem v* kann es nicht in int umgewandelt werden

gibt es dafür eine Möglichkeit dies zu Bereinigen?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Ein "Funktioniert nicht" ist eine schlechte Fehlerbeschreibung. Bei Deinem apply benutzt Du v ja gar nicht, und woher kommt das `self`?
Gib ein komplettes Beispiel, damit man Dir helfen kann.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was macht deiner Meinung nach apply? Woher kommt das v als Argument fuer das Lambda, und wo genau ist das in deinem zweiten Code-Snippet der "nicht funktioniert"?
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Das ist einmal der Code der dafür verantwortlich ist:

Code: Alles auswählen

      self.liste = []
   def xml(self): # xml File auswählen und im InfoFeld anzeigen lassen
      self.file_xml, _  = QFileDialog.getOpenFileName(self, 'Open file', 'c:\\',"Image files (*.flipxEnvSig)")
      self.ui.Info_xml.setText(self.file_xml)
      tree = ET.parse(self.file_xml)
      root = tree.getroot()
      for EnvSigConfigRow in root.iterfind("rows/EnvSigConfigRow"):
         self.liste.append((EnvSigConfigRow.findtext('name'), EnvSigConfigRow.findtext('formula'), EnvSigConfigRow.findtext('canId')))

   def export(self):
      if self.file_xml is None:
         None

      if self.file_asc is None:
         None

      if self.file_export is None:
         None

      else:
         with open(self.file_asc) as file: # Filtert alle ErrorFrames heraus, welche in der asc File befinden
            buffer = StringIO('\n'.join(line.strip(';\n') for line in file if not line.startswith('ErrorFrames')))

         # Zurechtschneiden und Filtern des asc Files
         self.df_all = pd.read_csv(buffer, sep = ";", skiprows = 5, skipinitialspace = True, converters = {'DATA L': partial(int, base = 16)})
         # Speichert den Filenamen für das Ploten
         file_title = os.path.basename(self.file_asc)

         if self.counter >= 1:
            df_Name_1 = self.df_all[self.df_all["ID"] == self.liste[0][2]]
            time_Name_1 = df_Name_1["Offset[s]"]
            values_Name_1 = df_Name_1["DATA L"].apply(lambda v: self.liste[0][1])

Das apply fügt etwas hinzu welches in der () steht
Das v als Argument habe ich vom vorherigen Code übernommen, jedoch war dort x und die Formel war x*(5/4095)*5.896
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das das apply etwas hinzufuegen wuerde ist ein bisschen sehr salopp und spricht nicht dafuer, dass du das begriffen hast, was da wirklich passiert. apply bekommt kein Argument, das dann "hinzugefuegt" wird (was auch immer das sein soll. Addition?). Sondern es bekommt eine Funktion oder allgemeiner ein Callable, und das muss ein Argument bekommen. Und einen Rueckgabewert liefern. Und dann wird dieses Callable auf JEDES Elemen in der Spalte angewandt, und der Wert vorher mit der Rueckgabe ersetzt.

Ein ...apply(lambda v: 10) ersetzt also alle Werte einfach mit 10. Egal was sie vonher waren. Ein ...apply(lambda v: v * 2) ersetzt sie mit dem Doppelten. Und .apply(lambda v: v*(5/1024)*9.980487805) ersetz sie eben mit v * einem Faktor der etwas kompliziert geschrieben ist.

Und was macht ..apply(lambda v: self.liste[0][1]) deiner Meinung nach dann, und wie verhaelt sich das zu dem, was da vorher stand?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird mit 4 Leerzeichen pro Ebene, nicht 3. Die `None` in den if-Blöcken sollen wohl `pass` sein, und besser ein `if self.file_xml is not None and self.file_asc is not None and self.file_export is not None:`.
`liste` ist ein sehr schlechter Name für eine was auch immer, denn das wird aus dem Namen nicht klar. Was soll das _1 an den ganzen Variablennamen? Und warum hast Du eine Liste, wenn die nur das erste Element interessiert?
Was versuchst Du denn mit dem `apply´ zu erreichen?
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Ich rücke da immer mit einem Tabulator ein, ist bei Python kein Problem 8)
Und was macht ..apply(lambda v: self.liste[0][1]) deiner Meinung nach dann, und wie verhaelt sich das zu dem, was da vorher stand?
In self.liste[0][1] ist die Formel v*(5/1024)*9.980487805 enthalten, da die Formel genau wie Name und ID vorher aus einer xml Datei ausgelesen worden sind. DIese Werte wurden dann in eine Liste gespeichert.

Wenn ich den Code jetzt so ausführe, wird die Formel als Wert eingesetzt und somit wird beim Ploten eine schöne gerade Linie ausgegeben.

Gibt es bei Python eine Funktion welche mir noch nicht bekannt ist um dieses Problem zu lösen?
Also etwas dass die Formel vielleicht ausrechnet ohne das v zu berücksichtigen?
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

@JohannX: nein, Dein Editor wandelt Tab in 3 Leerzeichen um, das solltest Du auf 4 Leerzeichen umstellen.

Wenn in der Liste ein String steht, der aussieht wie eine Formel, dann mußt Du diesen String erst in etwas umwandeln, mit dem Python rechnen kann. Welche Syntax kann so eine Stringformel haben? Woher weißt Du, welche Variable die Formel enthält?
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Sirius3 hat geschrieben: Montag 5. August 2019, 11:01 Eingerückt wird mit 4 Leerzeichen pro Ebene, nicht 3. Die `None` in den if-Blöcken sollen wohl `pass` sein, und besser ein `if self.file_xml is not None and self.file_asc is not None and self.file_export is not None:`.
`liste` ist ein sehr schlechter Name für eine was auch immer, denn das wird aus dem Namen nicht klar. Was soll das _1 an den ganzen Variablennamen? Und warum hast Du eine Liste, wenn die nur das erste Element interessiert?
Was versuchst Du denn mit dem `apply´ zu erreichen?
Ich versuche mit .apply einen Wert welcher sich mit (lambda v : self.liste[0][1]) befindet zu einem anderen Wert welcher in values_Name_1 = df_Name_1["DATA L"] vorhanden ist zu multiplizieren, sodass sich beim Ploten des gesamten projektes ein Diagramm erstellen lässt mit dem man Arbeiten kann.

Das "liste" ein schlechter Name ist ist ja auch in Ordnung. Deshalb habe ich ihn nun geändert "liste_in_welcher_die_xml_File_ausgelesen_und_die_notwendigen_Daten_gespeichert_werden"
Ist nun besser Nachvollziehbarer als vorhin 8)
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JohannX: Du rückst nicht mit einem Tabulator ein. Du verwendest vielleicht die Tabulator-*Taste*, die fügt bei Dir aber keinen Tabulator ein, sondern einscheinend drei Leerzeichen. Und das sollten halt *vier* statt drei sein.

In ``self.liste[0][1]`` ist keine Formel gespeichert, sondern eine Zeichenkette. Was da also steht ist ``.apply(lambda v: 'v*(5/1024)*9.980487805'`` was versucht jeden Wert in der Spalte durch die Zeichenkette 'v*(5/1024)*9.980487805' zu ersetzen. Da der Typ der Spalte aber `int` ist, wird versucht die Zeichenkette 'v*(5/1024)*9.980487805' in eine Zahl zu wandeln – was nicht geht, weil die Zeichenkette keine Darstellung einer Zahl enthält.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Sirius3 hat geschrieben: Montag 5. August 2019, 12:18 @JohannX: nein, Dein Editor wandelt Tab in 3 Leerzeichen um, das solltest Du auf 4 Leerzeichen umstellen.

Wenn in der Liste ein String steht, der aussieht wie eine Formel, dann mußt Du diesen String erst in etwas umwandeln, mit dem Python rechnen kann. Welche Syntax kann so eine Stringformel haben? Woher weißt Du, welche Variable die Formel enthält?
Laut dem Editor Studio Visual Code sind beim Tab Size: 4 eingestellt.
Als Syntax kenne ich "str, int, float" falls du das meinst
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

__blackjack__ hat geschrieben: Montag 5. August 2019, 12:20 @JohannX: Du rückst nicht mit einem Tabulator ein. Du verwendest vielleicht die Tabulator-*Taste*, die fügt bei Dir aber keinen Tabulator ein, sondern einscheinend drei Leerzeichen. Und das sollten halt *vier* statt drei sein.

In ``self.liste[0][1]`` ist keine Formel gespeichert, sondern eine Zeichenkette. Was da also steht ist ``.apply(lambda v: 'v*(5/1024)*9.980487805'`` was versucht jeden Wert in der Spalte durch die Zeichenkette 'v*(5/1024)*9.980487805' zu ersetzen. Da der Typ der Spalte aber `int` ist, wird versucht die Zeichenkette 'v*(5/1024)*9.980487805' in eine Zahl zu wandeln – was nicht geht, weil die Zeichenkette keine Darstellung einer Zahl enthält.
Danke, das war jetzt verständlich für mich, somit muss ich die ' ' wegbekommen :wink:
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Nein, Du hast ja irgendwoher dieses XML. Und darin ist sind Formeln, und diese müssen ja irgendeiner Syntax folgen. Hast Du eine Beschreibung des XML-Formats?

Und nein, Du mußt nicht die '' wegbekommen, sondern den String parsen, das heißt, in eine Form bringen, mit der Du rechnen kannst. Dazu müßte man aber wissen, nach welcher Syntax diese Formeln beschrieben sind.
Antworten