Rekursive Interpolationsformel: Anfängerprobleme

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.
Antworten
eufrat
User
Beiträge: 5
Registriert: Montag 29. Oktober 2018, 20:34

Hallo liebe Python-Nutzer,

ich bin Anfänger mit Python und habe ein paar Startschwierigkeiten.

Momentan versuche ich mich an der Programmierung einer rekursiven Formel für lineare Interpolation. Eine sehr einfache Anwendung, aber für mich als Anfänger nicht unproblematisch.

Ich habe einen vorgegebenen Funktionsverlauf durch eine Punktetabelle gegeben. Zwischen diesen Punkten möchte ich nun linear interpolieren. Ich habe eine Liste von x-Werten in meinem Code erstellt, die Python nacheinander in meine Formel einsetzen und mir die entsprechenden y-Werte ausspucken soll.

Die Formel für die Interpolation lautet:

yint = y1 + ((y2-y1)/(x2-x1))*(xint-x1)

Hier sind natürlich auch if-Bedingungen notwendig, damit Python die richtigen Werte für x1, x2, y1, y2 wählt. Denn für einen gesuchten interpolierten Wert yint für xint müssen x1, x2, y1 und y2 natürlich die Werte sein, die das Intervall bilden, in dem mein xint liegt.

Konkret am Beispiel:

x-Werte des Funktionsverlaufs: 1 , 2 , 3 , 4 , 5 , 6
y- Werte des Funktionsverlaufs: 0.8, -0.4, -0.2, 0.3, -0.2, -1

Ich suche jetzt die interpolierte y-Koordinate für meine x-Werte:
1.3, 2.4, 3.7, 4.4, 5.5, 5.8

Ich möchte erreichen, dass Python diese Liste abklappert und mir für jeden x-Wert den interpolierten y-Wert ausspuckt, wobei eine if-Bedingung sicherstellt, dass für die jeweiligen Werte die richtigen Werte für x1, x2, y1, y2 in die Formel eingesetzt werden.

Screenshot meines Codes:

https://ibb.co/jS61fq

In dem gezeigten Code ist die if Bedingung exemplarisch nur für den ersten Wert, xint = 1.3 vorhanden.

Soweit habe ich mit zwei Fehlermeldungen zu kämpfen:

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Python kann also einem array mit mehr als einem Element keinen Boolschen Wert zuweisen. Soweit klar, doch wie geht es anders? any und all funktionieren auch nicht so, wie ich es mir vorstelle.

Die zweite Fehlermeldung betrifft die Definition meiner Variablen x1, x2, y1 und y2. Ich habe einmal testweise versucht, die Variablen vor der If-Bedingung aufzuführen und ihnen einfach irgendwelche Werte zuzuweisen, damit Python diese Variablen auf dem Schirm hat, bevor diesen in der If-Bedingung ggf. neue Werte zugewiesen werden. Aber das geht sicher auch eleganter..

An dieser Stelle wäre ich für ein paar Tips bzw. Inspirationen bezgl. meines Codes sehr dankbar.

Viele Grüße

eufrat
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt eines Bildes solltest Du Deinen Code als Text posten.

Zum Interpolieren gibt es z.b. numpy.interp
Benutzeravatar
ThomasL
User
Beiträge: 1378
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Hier kannst du dir Anregungen holen
https://stackoverflow.com/questions/734 ... erpolation
Ich kann in deinem Code keinerlei Andeutungen von Rekursion erkennen, ist das nur eine Idee von dir oder "gefordert"?
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
eufrat
User
Beiträge: 5
Registriert: Montag 29. Oktober 2018, 20:34

Hallo zusammen,

rekursiv in dem Sinne, dass die Formel für die Interpolation für jedes Listenelement berechnet werden soll.

Ich möchte mich jetzt mal schrittweise annähern. Im Grunde ist mein Problem ja, dass mir die notwendige Syntax/Semantik fehlt, um für eine Liste mit mehreren Elementen if-Bedingungen zu erstellen, die für jedes Element abgefragt werden.

Dafür hab ich einen einfachen Testcode:

import numpy as np
lst1 = [1.3, 2.4, 3.7, 4.4, 5.5, 5.8]
x1 = np.array (lst1)
if x1 == 1.3:
x2 = 3
else:
x2 = 10
y = x1 + x2
print y

Also eine ganz einfache Funktion y mit der Summe von x1 und x2. Wenn Python nun die Liste abklappert, sollte er bei dem ersten Element merken: x1 ist gleich 1.3, also weise ich x2 den Wert 3 zu.

Klappt so erstmal nicht, weil einer Liste mit mehreren Elementen keine Boolschen Werte zugeordnet werden können. Soweit klar.

Versuche ich es mit .any:

import numpy as np
lst1 = [1.3, 2.4, 3.7, 4.4, 5.5, 5.8]
x1 = np.array (lst1)
if x1.any == 1.3:
x2 = 3
else:
x2 = 10
y = x1 + x2
print y

Ich verstehe diesen Code so, dass die if Bedingung erfüllt ist, wenn irgendeins meiner Listenelemente 1.3 ist. Das trifft zu, womit die Bedingung erfüllt sein müsste. Python sieht das aber anders, er nimmt den else-Fall.

Was ich erreichen möchte ist wie gesagt: Python klappert eine Liste ab und prüft für jedes Element einzeln if-Bedingungen, die dann jeweils in einer Wertezuweisung meiner Variablen münden.

Danke schonmal für eure Antworten!

Gruß
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Bitte gewoehn dir mal an, deinen Code in die dafuer vorgesehenen Tags zu setzen. Der verliert sonst alle Bedeutung. Dazu im vollstaendigen Editor auf </> klicken (mit dem Code vorher markiert), oder einfach [code*] [/code*] ohne * eintippen um den Code.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und zu deinem Code:

Fall 1: du vergleichst eine Liste von Dingen mit einem einzigen Ding. Was soll dabei rauskommen? Das kann doch niemals wahr sein, denn eine Liste von Sachen ist doch niemals eine Sache alleine. Das geht, weil Numpy daraus etwas anderes macht (dank Operatorueberladung): du bekommst eine Liste die so gross ist wie x1, und in jedem Eintrag steht, ob da ein Wert gleich 1.3 drin wahr. Also eine Liste von Booleans.

Fall2: du vergleichst eine Zahl mit einer Methode, die du nicht aufgerufen hast.

Ich verstehe auch ueberhaupt nicht, was du mit diesen Vergleichen ultimativ erreichen willst bezueglich deines Problems. Was dir hilft ist das paarweise betrachten der Liste, eine if-Abfrage kommt doch fuer eine solche Interpolation ueberhaupt nicht vor. Das kannst du zB mit der zip-Funktion erreichen. Ggf. bietet numpy auch noch was eigenes, aber ich wuerde da ersmal die Grundlagen betrachten.
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

@eufrat: formuliere erst einmal Dein Problem in Worten, was nacheinander zu tun ist, um eine Interpolation zu bekommen. Am besten fängst Du mit "gegeben ist ..." an, denn was Du wirklich gegeben hast, wird mir aus Deiner Beschreibung nicht klar. Weiter geht es mit "gesucht wird ...", "dazu wird in einem ersten Schritt ..." und so weiter.
eufrat
User
Beiträge: 5
Registriert: Montag 29. Oktober 2018, 20:34

Hallo,

was ist gegeben?

Ein Funktionsverlauf definiert durch 5 Punkte der Funktion.

Zum Beispiel eine Parabel y(x)=x²

P1 (1,1); P2 (2,4); P3 (3,9); P4 (4,16); P5 (5;25)

Zwischen diesen Punkten möchte ich interpolieren. Dafür nehme ich einfach mal 5 x-Werte:

xint:

1,3
2,1
3,4
4,8
5,2

Für diese x-Werte möchte ich mit der Interpolationsformel nun die y-Werte ausrechnen.

Die Formel ist:

yint = y1 + ((y2-y1)/(x2-x1))*(xint-x1)

yint und xint sind die interpolierten Koordinaten.

Die richtigen Werte x1,x2,y1 und y2 hängen davon ab, welchen Wert mein xint hat. Für 1,3 sind x1 und y1 die Koordinaten von P1 oben, und x2 und y2 die von P2.

Das möchte ich einfach erstmal mit einer verschachtelten If-Abfrage realisieren. Das mag nicht besonders elegant sein, zu mehr reicht es jedoch momentan bei Weitem nicht.

Gruß

eufrat
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

ich möchte zum Golfen auch gerne mein longboard benuzten. Das habe und kenne ich schon. Man kann damit aber kein Golf spielen. Bestenfalls von Loch zu Loch fahren.

Für dein Vorhaben brauchst du nunmal schleifen. Und musst deine Stützpunkte paarweise betrachten. Solange du dieses Problem nicht gelöst hast, kommt kein if zum tragen. Glaube es uns. DANN kannst du zb für eine gegebene x-Koordinate bestimmen per if, ob sie in einem gegebenen Intervall liegt.
Sirius3
User
Beiträge: 18267
Registriert: Sonntag 21. Oktober 2012, 17:20

@eufrat: Du hast gegeben, zwei Listen xvalues und yvalues, die gleich lang sind. Als Nebenbedingung muss man noch angeben, dass die x-Werte aufsteigend sortiert sind. Außerdem ist ein Wert x gegeben (dass Du mehrere davon hast, ist nur eine Verallgemeinerung).
Gesucht wird ein Wert y der sich aus der linearen Interpolation von yvalues an den Stützstellen xvalues ergibt.

Wie löst Du das Problem? Indem Du es in mehrere Teilprobleme auflöst:
Schritt 1: Finde den Index i, so dass xvalues[ i ] <= x < xvalues[i+1] gilt.
Schritt 2: Berechne y = yvalues[ i ] + (yvalues[i+1] - yvalues[ i ]) / (xvalues[i+1] - xvalues[ i ]) * (x - xvalues[ i ])

Ok, jetzt habe ich Schritt 2 schon ausprogrammiert, aber Schritt ein kannst Du z.B. mit Hilfe einer for-Schleife einfach lösen.
eufrat
User
Beiträge: 5
Registriert: Montag 29. Oktober 2018, 20:34

Hello again,

ich habe mir heute einiges an Tutorials reingezogen und habe dazu gelernt. Das Problem ist, dass man viele Funktionen sehr bald wieder vergisst, wenn man sie nicht praktisch anwendet. Das geht zumindest mir so.

Code: Alles auswählen

import numpy as np
xint = input ("Gib den X-Wert fuer die Interpolation an:  ")
lst1 = [1, 2, 3, 4, 5]
x = np.array(lst1)
lst2 = [1, 4, 9, 16, 25]
y = np.array(lst2)
i = 0
for x[i] in x:
    if x[i] <= xint < x[i+1]:
      yint = y[i] + ((y[i+1]-y[1])/(x[i+1]-x[i]))*(xint-x[i]) 
print x[0]
Ich habe meinen Ansatz leicht abgewandelt, nun soll vom Nutzer ein x-Wert eingegeben werden, für den er den interpolierten y-Wert haben möchte. Der Code ist noch allenfalls halbgar, denn i ist fix 0 gesetzt und noch kein mitlaufender Wert. Für einen x-Wert zwischen 1 und 2 würde es mit i =0 erstmal passen.

Bei dem dargestellten Code habe ich das Problem, dass Python mir sagt, dass x[0] = 5 ist, was ich nicht verstehe. (Eine testweise Interpolation für einen x-Wert zwischen 1 und 2 war falsch, daraufhin habe ich mir x[0] printen lassen, um zu schauen ob die richtigen Werte zugeordnet werden)

Es würde mir sehr weiterhelfen, wenn Ihr mir auf die Sprünge helfen könntet, wieso Python zu x[0]=5 kommt.

Grüße

eufrat
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was du da gebaut hast ist Unfug, den ich in dieser Form so noch nie gesehen habe. Wo hast du denn diese Idee her?

Code: Alles auswählen

>>> for x[0] in x: print(x)
... 
[1 2 3 4 5]
[2 2 3 4 5]
[3 2 3 4 5]
[4 2 3 4 5]
[5 2 3 4 5]
Du modifizierst also deine list in-Place.

ein simples

Code: Alles auswählen

for xleft, xright in zip(x[:-1], x[1:]):
      print(xleft, xright)
hilft schon mal. Numpy-arrays brauchst du übrigens nicht. Kannst du dir komplett sparen, und sie scheinen eher Verwirrung anzurichten.

Mein Beispiel ist übrigens einfach auf ein Array von x/y Koordinaten zu erweitern. Dazu musst du nur eine Liste mit Tupeln aus x/y-Koordinaten anlegen.
eufrat
User
Beiträge: 5
Registriert: Montag 29. Oktober 2018, 20:34

__deets__ hat geschrieben: Mittwoch 31. Oktober 2018, 20:35 Was du da gebaut hast ist Unfug, den ich in dieser Form so noch nie gesehen habe. Wo hast du denn diese Idee her?
Aua.

Nun gut, ich muss noch einiges lernen. Mein jetztiger Kenntnisstand ist unter aller Sau.

Weitere Anregungen sind natürlich willkommen. Ich werde mich derweil weiter durchwurschteln.

Achja, und bei der Interpolationsformel habe ich oben einen Fehler gemacht. Kann so natürlich nichts geben, weil der Term nach yi 0 wird.

Gruß
Antworten