Extremwerte, if else... Anfängerproblem

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Keranie
User
Beiträge: 9
Registriert: Dienstag 31. März 2015, 09:01

Hallo ich brauche mal eure Hilfe,
Ich habe Abflusswerte und eine Zeitreihe dazu und will jetzt die Extremwerte herauslesen.
Ich habe die Differenz der jeweiligen Abflussdaten genommen
qdat['Difference']=qdat['Abflusswerte'].diff()

und würde jetzt gerne irgendwie sowas machen:

if value(x) positv and nextvalue(x) negativ
return value(x)
else return pd.NaT

Also wenn der vorherige positiv ist und der nächste negativ (also einer meiner Maximalpunkt innerhalb einer Abflusskurve)
dann soll er den ersten rausschreiben und sonst alle anderen ungüntig machen.
Bin gerade erst angefangen mit Pyhton und Panda deshalb wäre es toll, wenn mir jemand helfen könnte :)
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@Keranie: Zuerst mit (qdat['Difference']>0).diff() die Übergänge zwischen positiven und negativen Werten berechnen und dann mit where nach 1en suchen.
Keranie
User
Beiträge: 9
Registriert: Dienstag 31. März 2015, 09:01

Hi,
ich habe es ein bisschen anders gelöst, wenn wahrscheinlich auch umständlicher aber immerhin es klappt:

Code: Alles auswählen

    xold=-999
    k=0
    for line in qdat['Difference']:
        xnew=line
        if xold >0 and xnew < 0:
            print qdat['Pegel'][[k]]            
        else:
            print 'false'
            xold=xnew
            k=k+1
Aber vielleicht kann kann mir nochmal jemand helfen wie ich nun das ganze in eine Datei bekommen?? :?: :?: (anstelle von print ausgabe sozusagen)
Ich bekommen immer ValueError: setting an array element with sequence, ich verstehe zwar was falsch ist, aber weiß nicht wie den wegbekommen ..
Zuletzt geändert von Anonymous am Donnerstag 16. April 2015, 10:04, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@Keranie: Das ist in der Tat umständlicher und nicht wirklich gut gelöst.

Statt -999 würde man besser einen ”einfacheren” Wert nehmen der die Bedinung erfüllt, also zum Beispiel -1 als erste negative Zahl, und ich würde auch kommentieren warum man den Wert zuweist.

`k` manuell hochzuzählen ist umständlich und fehleranfällig. Das würde man in der ``for``-Schleife mit `enumerate()` erledigen. Allerdings wird das nur zum Indexzugriff auf eine Sequenz verwendet, also braucht man es gar nicht wenn man die beiden Sequenzen mit `itertools.izip()` ”im Gleichschritt” iteriert.

`line` ist überflüssig und vom Namen her auch falsch.

Ist der Indexzugriff auf ``qdat['Pegel']`` wirklich *so* gewollt? Dir ist klar was für einen Typ der Wert hat der dort ausgegeben wird und warum das so ist? Du zeigst Deine Versuche das Ergebnis in eine Datei zu schreiben ja nicht, aber könnte es sein das genau hier das Problem besteht?

Die Zeilen 9 und 10 sind ziemlich sicher falsch eingerückt.

Ohne zu wissen was Du beim schreiben in eine Datei machst, kann man schlecht sagen was daran falsch ist. Man würde das auch eher von der Verarbeitung trennen, also statt ausgaben mit ``print`` oder in eine Datei zu machen, sollte in der Funktion ein Ergebnis (Liste, Array) erstellt werden, welches dann an anderer Stelle, ggf. mit einer eigenen Funktion, in eine Datei geschrieben wird.

Um das ``=`` bei Zuweisungen (ausser bei Defaultwerten in Funktionssignaturen und -aufrufen) und um binäre Operatoren werden üblicherweise Leerzeichen gesetzt um die Lesbarkeit zu verbessern.

Edit: In ”echtem” Python könnte das so aussehen:

Code: Alles auswählen

    previous_difference = -1
    for difference, level in izip(qdat['Difference'], qdat['Pegel']):
        print level if previous_difference > 0 and difference < 0 else 'false'
        previous_difference = difference
Letztendlich würde man aber besser die Möglichkeiten von `numpy` auch nutzen. Dafür ist es ja schliesslich da.
Keranie
User
Beiträge: 9
Registriert: Dienstag 31. März 2015, 09:01

@BlackJack wow super. Das hat schonmal richtig gut geholfen und läuft viel besser.
Daher sieht der Teil jetzt so aus:
-ich vergleiche
-und möchte die Werte als scalar value speicher
- diese hänge ich dann an mein DataFrame ran
-> Leider speichert er nur einen bzw. immer den selben Wert in meinem vektor... bei print in der console werden allerdings alle Werte richtig gelistet

Code: Alles auswählen

previous_difference = -1
for difference, level in zip(qdat['Difference'], qdat['Pegel']):
    print level if previous_difference > 0 and difference < 0 else 'false'
    def p_out(row):
        return (level) 
    previous_difference = difference

qdat['Peak']=qdat.apply(func = p_out, axis = 1)
qdat[['Pegel','Peak']].to_csv('peak.txt')
Bin ein totaler newbie mit python, vielleicht könnt ihr mir nochmal auf die sprünge helfe.. :)
Zuletzt geändert von Anonymous am Donnerstag 16. April 2015, 21:16, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
Keranie
User
Beiträge: 9
Registriert: Dienstag 31. März 2015, 09:01

Um die alle zu speichern brauche ich wohl eine Laufvariable...?
BlackJack

@Keranie: Du brauchst eine Ahnung von dem was Du da tust. ;-) Vielleicht wäre das Durcharbeiten von ein paar Tutorials nicht schlecht. Python-Grundlagen, Numpy, und Pandas jeweils. Sonst ist das einfach nur wildes Code-Raten und das funktioniert nicht wirklich.

In Deinem letzten Quelltext definierst Du in jedem Schleifendurchlauf eine neue Funktion, die aber letztendlich alle gleich sind, aber am Ende bleibt natürlich nur die vom letzten Durchlauf an den Namen `p_out` gebunden. Die Funktion nimmt ein Argument entgegen mit dem sie dann nichts macht. Das ist schon mal ein Warnzeichen das da was nicht stimmt. Und sie gibt einen Wert zurück über einen Namen der ausserhalb der Funktion gebunden wird. Zu dem Zeitpunkt wo die Funktion aufgerufen wird ist `level` an den Wert vom letzten Schleifendurchlauf gebunden, also an den letzten Wert von von ``qdat['Pegel']``. Und der wird bei jedem Aufruf zurückgegeben. Man hätte diese recht sinnfreie Funktion auch nur einmal vor der Schleife definieren können. Oder danach. Die Klammern um den Rückgabewert machen übrigens keinen Sinn.
Keranie
User
Beiträge: 9
Registriert: Dienstag 31. März 2015, 09:01

@BlackJack

ja das versuche ich ja nebenbei auch zu machen ;-) Trotzdem will ich eben nebenbei weiter am eigentlichen Ziel arbeiten.
Das die Funktion nur den letzten Wert übergibt, war mir eigentlich auch klar.
Ich weiß bloß nicht, wie ich es mache, dass alle Werte nacheinander gespeichert werden bzw. was sich anbietet?
zB. vorher eine Leere liste machen und dann die Werte mit append einfügen?
BlackJack

@Keranie: Ohne die Werkzeuge zu verstehen die zum Ziel führen bringt das aber vielleicht nicht so viel auf dieses Ziel hinzuarbeiten. Ich hatte ja nur Deinen Ansatz mit einer Schleife in Python-Code verbessert, das ist aber eigentlich nicht der Weg den man gehen würde, denn eigentlich verwendet man Numpy & Co ja um genau das zu vermeiden und die Schleifen zu verwenden die in den ”vektorisierten” Operationen auf diesen Datentypen implizit enthalten sind. Wie man an die Übergänge heran kommt hat Sirius3 ja gleich in der ersten Antwort zu der Frage geschrieben. Schau Dir die Operationen und die (Teil)Ergebnisse einfach mal ”live” in einer Python-Shell an.

Und dann müsstest Du klar formulieren wie eigentlich das Ergebnis aussehen soll. Denn bei der Ausgabe in der Schleife hast Du Zahlen mit der Zeichenkettenausgabe 'false' gemischt. Bei Numpy-Arrays kann man das so aber nicht sinnvoll mischen, da möchte man alle Werte von einem Datentyp haben. Da ist also die Frage was Du mit 'false' machen willst.
Antworten