xml und asc Files miteinander abgleichen

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.
Benutzeravatar
__blackjack__
User
Beiträge: 13925
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JohannX: Da wird nichts umgewandelt weil es den in `converters` angegeben Spaltennamen nicht geben kann wenn `skipinitialspace` gesetzt ist.

Wenn man statt der unverständlichen Indexwerte Namen verwenden würde, zum Beispiel bei einem `namedtuple`, fällt das auch eher auf wenn man einen Index daneben liegt, eben weil man dann sinnvolle, verständliche Namen stattdessen hätte…
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Ist mir auch grad aufgefallen, aber wenn ich den Code jetzt richtig annehme:

Code: Alles auswählen

self.df_all = pd.read_csv(self.file_asc, skiprows=5, delimiter=";", skipinitialspace = True, converters={'DATA L': partial(int, base=16)})
Kommt wieder diese Fehlermeldung raus:

Code: Alles auswählen

ValueError: invalid literal for int() with base 16: ''

Wobei ich diesen Code von meinem Vorgänger übernommen habe und ich nicht wirklich weiß was genau das macht:

Code: Alles auswählen

from functools import partial
converters={'DATA L': partial(int, base=16)}
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und hast du mal die Dokumentation von functools.partial angeschaut, um der Frage auf den Grund zu gehen, was das genau macht? In der steht ua genau der Fall den du hier hast als Beispiel (fuer binaer- statt hexadezimal-Zahlen) zur Erklaerung.
Benutzeravatar
__blackjack__
User
Beiträge: 13925
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JohannX: In der Spalte ist, wie schon mal gesagt, mindestens eine Zelle leer…
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
Benutzeravatar
kbr
User
Beiträge: 1501
Registriert: Mittwoch 15. Oktober 2008, 09:27

@JohannX: was passiert Deine Meinung nach eigentlich hier:

Code: Alles auswählen

values_Name_1 = df_Name_1["DATA L"].apply(lambda v: self.liste[0][1])
Benutzeravatar
snafu
User
Beiträge: 6831
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Man darf übrigens bei Fragen zu einem komplett neuen Thema gern einen neuen Thread aufmachen. Mit XML hat das hier ja schon lange nichts mehr zu tun...

EDIT: Achso, das steht nun mit der vorliegenden ASC-Datei in Zusammenhang. Es ist trotzdem unschön für spätere Leser, wenn man einen Sammelthread für all seine Fragen bezüglich eines Projektes aufmacht. Denn dann muss auch viel uninteressanter Kram durchforstet werden. Daher bei der Nutzung des Forums vielleicht nicht nur sich selbst sehen, sondern auch die Nutzergemeinschaft im Blick haben. Das wäre sehr nett. :)
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

kbr hat geschrieben: Donnerstag 1. August 2019, 17:18 @JohannX: was passiert Deine Meinung nach eigentlich hier:

Code: Alles auswählen

values_Name_1 = df_Name_1["DATA L"].apply(lambda v: self.liste[0][1])
Also meines Wissens nach wird hier self.liste[0][1] diese Formel eingesetzt v*(5/1024)*9.980487805
Das .apply Berechnet den Wert zu welcher sich in df_Name_1["DATA L"] befindet
Das ganze wird dann in eine neue Variable gespeichert
Denke dass das so Richtig ist.
Benutzeravatar
sparrow
User
Beiträge: 4506
Registriert: Freitag 17. April 2009, 10:28

Das schöne an Python ist, dass man gar nicht 'denken' (im Sinne von vermuten) muss, man kann das einfach ausprobieren.
Befinden sich denn hinterher die korrekten Daten in values_Name_1? So wie du sie erwartest?
Ich sehe zumindest nicht, warum die von dir genannte Formel dort eingesetzt werden sollte. Was ist denn der Wert von self.liste[0][1] (der Name ist noch immer schlecht, das mit den Indexzugriffen auch. Wäre das gut gelöst, müsste man das nicht zum 18 Mal fragen).
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Aber ich habe jetzt in de asc File herausgefunden warum das so nicht hinhaut:
Es ist ein Error enthalten
ErrorFrames: 0 6611826 1 0 0 12
Das dürfte mir den Fehler verursachen...

Also muss ich vorher die asc File nach solchen leeren Zeilen durchsuchen und entfernen.
Dieser Vorgang sollte korrekt sein
Benutzeravatar
sparrow
User
Beiträge: 4506
Registriert: Freitag 17. April 2009, 10:28

Es wird spätestens an der von snafu angesprochenen Stelle nicht mehr korrekt sein.
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Das Programm funktioniert soweit wie es soll.
Zwei Sachen müssen noch etwas angepasst werden, wobei ich das erste schon geschafft habe.

Das zweite und etwas aufwendigere Problem ist folgendes:
Im asc File sind noch weitere Daten vorhanden als die von dem xml File, diese sind Fehlerdaten welche so aussehen könnten: 1100001x
Sie haben immer einen 1 und ein x am Ende, davor kann es Variieren.

ABER:
Es darf nicht die Daten vom xml File miteinbeziehen, da diese so aussehen,

Code: Alles auswählen

DD00011x
1100013
1100015
könnte man meinen dass DD00011x auch ein Fehler wäre, ist er aber nicht.

Wie kann ich dieses Vorhaben umsetzen?
Wenn am Ende 1x steht und nicht im xml steht, dann in eine neue Variable speichern und plotten via plotly
Sirius3
User
Beiträge: 18217
Registriert: Sonntag 21. Oktober 2012, 17:20

Du schaust einfach, ob die ID mit 1x endet und nicht im XML-File steht.
Niemand hier weiß, was Du für Datenstrukturen hast und was speichern und plotten genau bedeutet.
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Ich habe nach Wunsch den Kollegen nun 2 Input Felder zu der GUI hinzugefügt, so können 2 ID´s welche irgendwelche Meldungen sein können.
Soweit funktioniert das auch und kann als Diagramm via Plotly ausgegeben werden.

Eine Frage habe ich hier allerdings, bei einer ID z.B. 1100001x sind mehrere unterschiedliche Daten vorhanden

Code: Alles auswählen

1100001x;800A5F20
1100001x;800A5F6D
1100001x;800A5FE1
1100001x;800A5FEF
1100001x;800A6024
1100001x;800A6039
1100001x;800A6071
1100001x;800A6A7D
1100001x;800A6B29
1100001x;800A6B60
1100001x;800A6B6E
1100001x;800A6B8D
1100001x;800A7229
1100001x;800A7279
1100001x;800A7319
1100001x;800A73B9
1100001x;800A5F6D
Das ist nur ein kleiner Auszug von der csv Datei.

Da dieses Unterfangen mein "können" überfordern, muss ich hier nochmals nachfragen.
Wie stelle ich es am besten an, damit alle gleichen Daten von der ID 1100001x seperat abgespeichert werden und diese mit hilfe von plotly in das Diagramm angezeigt werden kann?

Derzeit sieht mein Code so aus:

Code: Alles auswählen

            df_Error1 = self.df_all[self.df_all["ID"] == self.ui.line_BaseID_11.text()]
            time_Error1 = df_Error1["Offset[s]"] # Holt sich die Zeit
            values_Error1 = df_Error1["DATA L"]
            name_Error1 = self.ui.line_Name_11.text() # Name für Layout
            self.fig.add_trace(go.Scatter(x = time_Error1, y = values_Error1, mode = "markers", name = name_Error1))
Hier werden jedoch alle 1100001x zusammengefasst ausgegeben
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Ich wage meine Versuche mit regex und das Problem zu lösen.
Das ist der Code:

Code: Alles auswählen

import re
import sys
import os
import pandas as pd
from io import StringIO

neue = []

with open("DUT4_Slow_Decrease_Increase_10V_Messages_All_Flipx_.asc", "r") as file:
        buffer = StringIO('\n'.join(line.strip(';\n') for line in file if not line.startswith('ErrorFrames')))
        for lines in buffer:
                neue.append(lines)

regex = r'1100001x;([0-9a-fA-F]+)'
matches = re.finditer(regex, neue, re.MULTILINE)

for matchNum, match in enumerate(matches, start=1):
    
    print ("Match {matchNum} was found at {start}-{end}: {match}".format(matchNum = matchNum, start = match.start(), end = match.end(), match = match.group()))
    
    for groupNum in range(0, len(match.groups())):
        groupNum = groupNum + 1
        
        print ("Group {groupNum} found at {start}-{end}: {group}".format(groupNum = groupNum, start = match.start(groupNum), end = match.end(groupNum), group = match.group(groupNum)))
Doch leider kommt diese Fehlermeldung:

Code: Alles auswählen

Traceback (most recent call last):
  File "regex.py", line 17, in <module>
    matches = re.finditer(regex, neue, re.MULTILINE)
  File "C:\Python3\lib\re.py", line 230, in finditer
    return _compile(pattern, flags).finditer(string)
TypeError: expected string or bytes-like object
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Reguelaere Ausdruecke arbeiten auf Strings (oder Bytes). Nicht auf Listen.
Benutzeravatar
__blackjack__
User
Beiträge: 13925
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich frage mich auch was das überhaupt werden soll – das sind doch immer noch durch Semikolon getrennte CSV-Daten die danach in einen Pandas-DataFrame gefüttert werden, oder? Warum will man da jetzt *vorher* irgendwie mit regulären Ausdrücken Werte für eine Spalte suchen wenn man das viel einfacher und robuster um DataFrame machen könnte‽
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Ich lese die csv Datei mittels Pandas ein und filtere hier ErrorFrames heraus:

Code: Alles auswählen

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)
         
                  print(self.df_all.head())
Die Ausgabe davon:

Code: Alles auswählen

   Start Date      Time  Offset[s]        ID    DATA H      DATA L
0  27.03.2019  17:18:26     0.0010       AEx  00000000  1279872594
1  27.03.2019  17:18:26     0.0013  2200000x  700017E9  1279872594
2  27.03.2019  17:18:26     0.0016  DD00011x  8002019E         223
3  27.03.2019  17:18:26     0.0019  DD00011x  8002019E         210
4  27.03.2019  17:18:26     0.0045  1100001x  800A7229           2
Das ist super Einfach mit Pandas, jetzt stehe ich seit Gestern an dem Problem, dass ich gern von der Spalte "ID" alle Fehler mit 1100001x haben möchte, davon allerdings nur den Fehler z.B: 800A7229 welcher sich in der Spalte "DATA H" befindet!
Sirius3
User
Beiträge: 18217
Registriert: Sonntag 21. Oktober 2012, 17:20

Das `line.strip(';\n')` sollte ein `line.rstrip(';\n')` sein.
Und in der ID-Spalte stehen keine Spalten-Namen drin, so dass der Aufruf nicht funktioniert. Was hast Du Dir denn bei der ersten Zeile gedacht?

Was Du brauchst sind Vektoren mit Wahrheitswerten, die Du logisch verknüpfen kannst.
Benutzeravatar
__blackjack__
User
Beiträge: 13925
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@JohannX: Naja dann mach das doch einfach. Du weisst ja wie man alle Datansätze mit der ID 1100001x selektiert. Und Du weisst wie man alle Datensätze mit "DATA H"-Wert 800A7229 selektiert. Grundsätzlich könntest Du das Problem also schon lösen. Statt zwei Schritte zu machen die Du bereits kennst, kann man das auch in einen Schritt kombinieren.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
JohannX
User
Beiträge: 110
Registriert: Mittwoch 27. März 2019, 17:07

Das mit der Wahrheitstabelle klingt nach einem guten Ansatz, habe es hiermit probiert:

Code: Alles auswählen

df_Error1 = self.df_all[self.df_all["ID"] == self.ui.error_Base_1.text()]
            print(df_Error1.head())
            df_Error1_1 = df_Error1["DATA H"] == self.ui.error_flt_1.text()
            print(df_Error1_1.head())
            if df_Error1_1 == True:
               time_Error1 = self.df_all["Offset[s]"]
               values_Error1 = self.df_all["DATA L"]
               name_Error1 = self.ui.error_Name_1.text() + " - " + self.ui.error_Base_1.text() + "." + self.ui.error_flt_1.text()
               self.fig.add_trace(go.Scatter(x = time_Error1, y = values_Error1, mode = "markers", name = name_Error1), secondary_y = True)
Doch da bekomme ich folgende Fehlermeldung:

Code: Alles auswählen

    Start Date      Time  Offset[s]        ID    DATA H  DATA L
4   27.03.2019  17:18:26     0.0045  1100001x  800A7229       2
5   27.03.2019  17:18:26     0.0048  1100001x  800A7279       2
6   27.03.2019  17:18:26     0.0050  1100001x  800A7319       2
7   27.03.2019  17:18:26     0.0053  1100001x  800A73B9       2
21  27.03.2019  17:18:26     0.0845  1100001x  800A7229       2
4      True
5     False
6     False
7     False
21     True
Name: DATA H, dtype: bool
Traceback (most recent call last):
  File "ascFileReader.py", line 270, in export
    if df_Error1_1 == True:
  File "C:\Python3\lib\site-packages\pandas\core\generic.py", line 1556, in __nonzero__
    self.__class__.__name__
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
@ __blackjack__:
ja ich weiß wie ich diese Datensätze einzeln selektieren kann, das ist soweit kein Problem, falls ich daraus einen Schritt machen möchte, würde das so aussehen???

Code: Alles auswählen

df_Error1 = self.df_all[self.df_all["ID"], self.df_all[self.df_all["DATA H"] == self.ui.error_Base_1.text(), self.ui.error_flt_1.text()]]
Antworten