Maximalwerte auslesen

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
raymike
User
Beiträge: 2
Registriert: Samstag 21. Mai 2016, 11:05

Hallo liebe Community,

momentan bin ich noch relativ unerfahren mit python und es erschließt sich mir ein ganz zentraler Zusammenhang nicht. Für Hilfe wäre ich überaus dankbar!

Ich möchte Maximalwerte eines Signals über eine bestimmte Zeit auslesen. Hierzu hab ich folgendes geschrieben:

Code: Alles auswählen

t=[0,1,2,3,4,5,6,7,8,9,10,12,50]
F=[2,3,4,5,1239,182,18492,9,34,345923,234,123,9]
tau2=[20,18,17,16,16,16,16,16,16,16,16]
begin=list([0])
MaxF=list()
i,k=0

for k in range(0,2):
    zeit=t
    kraft=F
    for i in range(0,len(zeit)):
        if zeit[i]>=zeit[begin[k]] and zeit[i]<(zeit[begin[k]]+tau2[k]):
            zeit[i] = zeit[i]*1
            kraft[i] = kraft[i]*1
        else:
            zeit[i]=zeit[i]*0
            kraft[i]=kraft[i]*0

    MaxF.append(max(kraft))
    for index, item in enumerate(kraft):
        if item == max(kraft):
            begin.append(index)
Die Eingangswerte für t und F sind hier von mir ausgedachte Testwerte. Der Code ansich ist sehr ineffizient- dessen bin ich mir bewusst.
Mir ist jedoch eine sehr gravierende Sache aufgefallen: Ich habe vorher t und F ausgelesen und diese sind somit "fest definiert". Nun möchte ich zu Beginn der ersten Schleife alle Werte aus t und F in zeit und kraft speichern. Mit Hilfe der nächsten Schleifen wird dann der Maximalwert gesucht. Im nächsten Iterationsschritt sollen zeit und kraft erneut mit t und F überschrieben werden. Aber t und F haben sich analog zu zeit und kraft verändert. Warum? In Matlab z.B. funktioniert es genau so. Ich habe das Gefühl etwas grundlegendes nicht verstanden zu haben...

Vielen Dank falls jemand helfen kann und möchte!

VIele Grüße
raymike
Zuletzt geändert von Anonymous am Samstag 21. Mai 2016, 12:13, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@raymike: Python kopiert bei Zuweisungen niemals von sich aus Werte. Wenn Du ``a = b`` schreibst, dann sind beide Namen an das *selbe* Objekt gebunden, das heisst wenn man das Objekt verändert, dann verändert man *das* *eine* Objekt welches an die beiden Namen gebunden ist. Falls das beispielsweise eine Liste ist, dann haben ``a[0] = 42`` und ``b[0] = 42`` den gleichen Effekt, weil es die selbe Liste ist. Wenn Du eine Kopie einer Liste an einen Namen binden möchtest, dann musst Du selbst dafür sorgen das eine Kopie erstellt wird. Zum Beispiel mit Methoden/Operationen für den speziellen Typ, also beispielsweise die `list()`-Funktion (``a = list(b)``), oder „slicing“ (``a = b[:]``), oder in Python 3 mit der `copy()`-Methode (``a = b.copy()``), oder allgemein mit der `copy()`-Funktion aus dem `copy`-Modul. Wobei all diese Alternativen nur eine flache Kopie erstellen. Letztendlich erzeugt man in der Regel eher neue Datenstrukturen als vorhandene zu kopieren und dann zu verändern. Das ist weniger fehleranfällig, weil man dann sicher ist, dass sich Änderungen nicht irgendwo anders auswirken, weil man dort auf das selbe Objekt zugriff hat.
BlackJack

@raymike: Der Code läuft so übrigens nur bis Zeile 6, da versuchst Du einen Wert auf zwei Namen zu verteilen, was nicht geht. Die Zeile macht aber sowieso keinen Sinn.

Bei der Definition von `begin` ist der `list()`-Aufruf überflüssig.

Die ``if``-Bedingung kann man ohne das ``and`` mit Operatorverkettung ”mathematischer” formulieren. Also statt ``x >= a and x < b`` kann man ``a < x < b`` schreiben.

Die Faktoren 1 und 0 machen zumindest bei dem Beispiel keinen Sinn. Das würde Sinn machen falls NaN-Werte in den Daten vorkommen können und man die im ”0-Fall” behalten möchte.

``for``-Schleifen über Zahlen die dann als Indexwerte in Sequenzen verwendet werden sind in Python ein „anti-pattern“. Man kann ohne den Umweg über einen Index direkt über die Elemente von Sequenzen iterieren. Wenn man über ”parallele” Sequenzen iterieren möchte, gibt es die `zip()`- bzw. `itertools.izip()`-Funktion.

So als Zwischenergebnis könnte man hier angelangen (ungetestet):

Code: Alles auswählen

#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
from itertools import izip


def main():
    t = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 50]
    F = [2, 3, 4, 5, 1239, 182, 18492, 9, 34, 345923, 234, 123, 9]
    tau2 = [20, 18, 17, 16, 16, 16, 16, 16, 16, 16, 16]
    begin = [0]
    max_f = list()
    
    for i in xrange(0, 2):
        zeit = list()
        kraft = list()
        for z, k in izip(t, F):
            if t[begin[i]] < z < t[begin[i]] + tau2[i]:
                zeit.append(z)
                kraft.append(k)
            else:
                # 
                # TODO Factor 0 really necessary here?  NaNs!?
                # 
                zeit.append(z * 0)
                kraft.append(k * 0)
     
        max_kraft = max(kraft)
        begin.extend(i for i, v in enumerate(kraft) if v == max_kraft)
        max_f.append(max_kraft)


if __name__ == '__main__':
    main()
Wobei man hier ganz dringend die Namen überarbeiten sollte. Die Mathematik ist meistens kein gutes Vorbild für Variablennamen in Programmen. Bei Formeln wird Wert auf Kompaktheit gelegt. Bei Programmen dagegen ist Verständlichkeit gefragt. Man sollte das auch ohne Kommentare verstehen können, die einem erklären was `t` und `F` für eine Bedeutung haben. Man sollte aus dem Namen auch Informationen ziehen können ob es sich um einen Wert, oder um einen Containertyp handelt. Das wird üblicherweise durch Einzahl/Mehrzahl ausgedrückt. `forces` ist eine Sammlung von Kraftwerten, während `force` für einen Wert steht. Auch sollte man das mischen von verschiedenen natürlichen Sprachen bei der Benennung vermeiden. In ein und der selben Funktion `force`, `forces`, `kraft`, und `kraefte` zu haben ist nicht übersichtlich.
raymike
User
Beiträge: 2
Registriert: Samstag 21. Mai 2016, 11:05

Vielen Dank BlackJack für deine ausführlichen Erklärungen, Anmerkungen und Tipps!
Ich werde diese durcharbeiten und bescheid geben ob ich das kleine Programm zum Laufen bringen konnte! :)
Antworten