Daten verschiedener Serien in einer Reihe vergleichen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Jenson
User
Beiträge: 7
Registriert: Freitag 16. März 2018, 21:59

Guten Morgen Zusammen,

ich sitze nun schon seit einigen Tage an folgendem Problem und komme trotz unzähliger Versuch nicht zum Ziel. Heir mal eine Beschreibung.
Es geht vom Prinzip her um folgende Daten:
f1 f10 f11 f12 f2 f3 f4 f5 f6 f7 f8 f9 temp
0 181 2560 2703 3074 635 717 885 988 1479 1616 2030 2164 21
1 182 2560 2717 3074 635 717 885 988 1478 1615 2029 2164 21
2 181 2560 2702 3074 635 717 885 988 1479 1616 2030 2164 21
3 182 2560 2716 3074 635 717 885 988 1478 1616 2029 2164 21
4 181 2560 2703 3074 635 717 885 988 1479 1616 2030 2164 21
5 181 2560 2702 3074 635 717 885 988 1478 1615 2029 2165 21
6 181 2560 2702 3074 635 717 885 988 1478 1615 2029 2165 21
7 182 2560 2716 3074 635 717 885 988 1478 1615 2029 2164 21
8 182 2560 2703 3074 635 717 885 988 1478 1615 2029 2164 21
9 181 2560 2703 3074 635 717 885 988 1479 1616 2030 2163 21
10 181 2560 2702 3074 635 717 885 988 1478 1615 2029 2165 21
11 181 2560 2702 3074 635 717 885 988 1478 1615 2029 2165 21
12 182 2560 2702 3074 635 717 885 988 1478 1615 2029 2164 21
13 182 2557 3070 3229 638 734 884 988 1480 1618 2029 2165 26
14 182 2557 3070 3229 638 734 883 988 1480 1616 2029 2166 26
15 182 2558 3070 3197 638 734 883 988 1480 1633 2029 2166 26
16 182 3070 3197 3583 638 733 884 988 1480 2029 2166 2558 26
17 182 2720 3070 3195 638 733 884 988 1480 2029 2166 2558 26
18 181 2714 3071 3179 717 806 946 1478 1615 2028 2164 2558 22
19 182 3601 0 0 737 886 993 1491 2038 2565 2669 3077 41
es geht um ingesammt 700K Datenreihen. Ich kann nicht ausschliessen dass sich nicht irgendwo ein NaN oder sonstiger Fehler eingeschlichen hat. Aber wenn, dann sollten es relativ wenige sein.

Ziel der ganzen Analyse soll sein, eine weitere Spalte zuzufügen, welche die Differenz zweier Einträge enthält, die aber nicht immer an der gleichen Stelle im DataFrame stehen, wohl aber immer in gleichen Bereich liegen.
Beispiel: Reihe 0 f8 - f6 (2030 - 1479) = 551
Reihe 18 f7 - f5 (2028 - 1478) = 550

Diese Schwankungen der Position erstrecken sich nicht über alle Einträge, sondern spielen sich im Rahmen der Positionen 4 - 9 ab.

hier mein Code:

Code: Alles auswählen


import pandas as pd
import numpy

def calc_diff(x):
    Echo1 = 1
    Echo2 = 2
    Found1 = 0
    
    if type(x['f4']) == numpy.int64 and x['f4'] > 1470 and x['f4'] < 1530:
        Echo1 = x['f4']
        Found1 = 4

    elif type(x['f5']) == numpy.int64 and x['f5'] > 1470 and x['f5'] < 1530:
        Echo1 = x['f5']
        Found1 = 5

    elif type(x['f6']) == numpy.int64 and x['f6'] > 1470 and x['f6'] < 1530:
        Echo1 = x['f6']
        Found1 = 6

    if Found1 == 4:
        if type(x['f5']) == numpy.int64 and x['f5'] > 2010 and x['f5'] < 2080:
            Echo2 = x['f5']
        elif type(x['f6']) == numpy.int64 and x['f6'] > 2010 and x['f6'] < 2080:
            Echo2 = x['f6']

    elif Found1 == 5:
        if type(x['f6']) == numpy.int64 and x['f6'] > 2010 and x['f6'] < 2080:
            Echo2 = x['f6']
        elif type(x['f7']) == numpy.int64 and x['f7'] > 2010 and x['f7'] < 2080:
            Echo2 = x['f7']

    elif Found1 == 6:
        if type(x['f7']) == numpy.int64 and x['f7'] > 2010 and x['f7'] < 2080:
            Echo2 = x['f7']
        elif type(x['f8']) == numpy.int64 and x['f8'] > 2010 and x['f8'] < 2080:
            Echo2 = x['f8']

    return Echo2 - Echo1
    
    
daten = pd.read_csv("test_minimal.csv", sep="\t", low_memory=False)
daten = daten.replace('NaN', 0)
differenz = daten.apply(calc_diff, axis=1)
daten['diffs'] = pd.Series(differenz)
daten.to_csv("test_minimal_mod.csv", sep = '\t')
Wenn ich diesen Code mit meinem minimalbeispiel laufen lasse, dann funktioniert alle wie es soll. Wenn ich allerding die kompletten Daten reinjage, dann kommt folgendes dabei heraus:
Unnamed: 0 f1 f10 f11 f12 f2 f3 f4 f5 f6 f7 f8 f9 temp diffs
0 0 181 2560 2703 3074.0 635 717 885 988 1479 1616 2030 2164 21 1
1 1 182 2560 2717 3074.0 635 717 885 988 1478 1615 2029 2164 21 1
2 2 181 2560 2702 3074.0 635 717 885 988 1479 1616 2030 2164 21 1
3 3 182 2560 2716 3074.0 635 717 885 988 1478 1616 2029 2164 21 1
4 4 181 2560 2703 3074.0 635 717 885 988 1479 1616 2030 2164 21 1
5 5 181 2560 2702 3074.0 635 717 885 988 1478 1615 2029 2165 21 1
6 6 181 2560 2702 3074.0 635 717 885 988 1478 1615 2029 2165 21 1
ich habe keine Ahnung warum er beim Eintrag f12 plötzlich eine float einbaut und noch weniger verstehe ich warum er eine weitere Indexspalte vorne hinzufügt....

Bitte, hatte jemand dieses Problem schon mal gehabt oder sonstwie eine Idee für mich was ich falsch mache.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jenson: die Datei an sich ist ja schonmal verkorkst. Woher kommen die Daten? Wer kam auf die Idee, die Spalten lexikalisch nach Namen zu sortieren?

Variablennamen werden grundsätzlich klein geschrieben. Warum hat `Found1` eine 1? Auf Typen zu prüfen ist selten sinnvoll, hier macht es überhaupt keinen Sinn, da entweder die gesamte Spalte vom Typ int ist, oder nicht. Wenn kein `Found1` gesetzt wurde ist diff 1, ist das so gewollt? Sollte es nicht eine Warnmeldung geben?

Da `Found1` nur gesetzt wird um später wieder per if auseinander genommen zu werden, könnte man die zwei if-Kaskaden einfach zusammennehmen. Besser wäre es, die Logik der einzelnen if-Zweige zu einem Fall zu kombinieren:

Code: Alles auswählen

def calc_diff(x):
    for row in [4, 5, 6]:
        if 1470 < x['f%d' % row] < 1530:
            break
    else:
        print "Warnung: erste Spalte nicht gefunden"
        return 1
    
    for row2 in [row + 1, row + 2]:
        if 2010 < x['f%d' % row2] < 2080:
            break
    else:
        print "Warnung: zweite Spalte nicht gefunden"
        return 1

    return x['f%d' % row2] - x['f%d' % row]
Zu den anderen Problemen: In Spalte f12 scheint irgendwo ein Float zu stehen (oder NaN, was das selbe ist). Für die zusätzliche Spalte habe ich im Moment auch keine Erklärung, außer dass irgendwo mehr Zahlen in einer Zeile stehen als angenommen.

Auf jeden Fall solltest Du die Datei erst von Fehlern bereinigen, bevor Du damit weiterarbeitest.
Jenson
User
Beiträge: 7
Registriert: Freitag 16. März 2018, 21:59

@Sirius3:
Danke für die Antwort! Die Datei sieht in wirklichkeit etwas besser aus;-) Beim hierher kopieren sind die Tabs irgendwie verschwunden... Das mit dem Sortieren der Spalten passierte automatisch, hätte es auch lieber 1,2,3, usw gehabt aber egal...

Mit dem Datenaufräumen und deinem sortierer hats geklappt.

Code: Alles auswählen

daten['f1'] = pd.to_numeric(daten['f1'], errors='coerce')
meine Unnamed zeilen bin ich auch los geworden.;-)

Code: Alles auswählen

cols = [col for col in daten if not col.startswith('Unnamed:')]
Was mich allerdings noch wurmt ist das er immernoch bestimmte Spalten als float ausgiebt obwohl ich alle als int einlese...

f1 f10 f11 f12 f2 f3 f4 f5 f6 f7 f8 f9 temp diffs
0 181 2560 2703 3074.0 635.0 717 885 988.0 1479 1616 2030 2164 21 551.0
1 182 2560 2717 3074.0 635.0 717 885 988.0 1478 1615 2029 2164 21 551.0
2 181 2560 2702 3074.0 635.0 717 885 988.0 1479 1616 2030 2164 21 551.0
3 182 2560 2716 3074.0 635.0 717 885 988.0 1478 1616 2029 2164 21 551.0
Aber soweit ist mein Hauptproblem erstmal gelößt!
Danke
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jenson: Du hast keine Lösung gefunden, sondern nur an den Symptomen herumgedoktort. Wenn Du fehlerhafte Daten hast, mußt Du erst die Fehler bereinigen. Als ersten Schritt mußt Du also Zeile für Zeile die Datei durchgehen und prüfen, ob sie dem gewünschten Format entspricht und andernfalls entweder Reparieren oder Ingorieren, je nachdem, was sinnvoller ist.

Code: Alles auswählen

with open("yourfile.csv") as lines:
    _header = next(lines) # ignore header
    for num, line in enumerate(lines, start=2):
        parts = line.split()
        if len(parts) != 14 or not all(d.isdigit() for d in parts):
            print("Fehlerhafte Zeile {}: {!r}".format(num, line))
Besser wäre es natürlich, erst gar keine fehlerhaften Dateien zu schreiben; wer also erzeugt die Datei und kann man daran etwas ändern?
Antworten