Benötige Hilfe bei Formeln in einer Schleife

  • Hallo zusammen,

    ich möchte euch gerne eine Funktion zeigen, bei deren Mathematik ich mir das Hirn zermartere.
    Eine korrete (mit Hand nachgerechnet) Lösung gibt sie nun aus, aber ich habe einen ganzen Abend damit zugebracht.
    Jetzt ist die große Frage, ob das nicht wesentlich einfacher geht ;)

    Also, erst mal zum Hintergrund:
    Mein Programm ruft sich bei OpenWeatherMap.org eine Wettervorhersage in Form eines JSON Strings.
    In der hier gezeigten Funktion möchte ich mir eine künstliche Temperatur ausrechnen, welche zwei Dinge berücksichtigt:
    1) Gewichtung der Vorhersage
    2) Anzahl der Tage

    Meine Schwierigkeit liegt darin, dass die Anzahl der Tage einen Einfluss auf die Gewichtungsfaktoren haben.
    Erklären kann ich das nicht so richtig, also mal zwei Beispiele.

    Beispiel 1:
    Gewichtungsfaktor: 0.7
    Tage: 2
    Temperatur = Temperatur_1 * 0.7 + Temperatur_2 * 0.3 bzw.
    Temperatur = Temperatur_1 * 0.7 + Temperatur_2 * (1 - 0.7)


    Beispiel 2:
    Gewichtungsfaktor: 0.8
    Tage: 3
    Temperatur = Temperatur_1 * 0.8 + Temperatur_2 * 0.16 + Temperatur_3 * 0.04 bzw.
    Temperatur = Temperatur_1 * 0.8 + (Temperatur_2 * 0.8 + Temperatur_3 * 0.2 ) * 0.2

    Kann ich das alles in einer einzigen Schleife erledigen?
    --- Momentan läuft die Schleife ja quasi einen Tag zu wenig, und danach wird der gesamte try-except Block wiederholt, weil ich das letzte Element einen anderen Faktor brauche.

    Vielen Dank vorweg für Tipps!

    Gruß,
    Marcus


    PS: Sofern da weiterer Kontext nötig ist: https://github.com/mzurhorst/wass…weather_data.py
    (läuft allerdings nicht ohne einen separaten API-Key, den ich da nicht hochladen wollte. Bei Interesse gerne PM an mich)

  • Probiers mal damit:


    So ähnlich...

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

    Einmal editiert, zuletzt von Gnom (3. August 2017 um 08:33)

  • Das klappt noch nicht so ganz. So gibt es nur den letzten Faktor aus. Fehlt noch das Multiplizieren einzelnen Faktoren mit den Messwerten und das Aufaddieren. Ganz trivial ist das nicht. Der letzte Restfaktor muss außerhalb der Schleife verarbeitet werden.
    So funktionierts:

    Sind noch zwei Prints drin zum Prüfen der Berechnung. Ausgabe ist hier:

    1 0.8 8
    2 0.15999999999999998 11.2
    3 0.03199999999999999 12.159999999999998
    4 0.007999999999999995 12.479999999999999

    Komischerweise kriege ich bei den Faktoren seltsame Zahlen mit Rundungsfehlern - weiß jemand warum? (Hab einen online Python-Interpreter benutzt, weil gerade kein Pi hier... ;)

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

    Einmal editiert, zuletzt von Gnom (3. August 2017 um 09:16)

  • Ich hatte die Originalfrage nicht genau genug gelesen :no_sad:

    Das Ziel ist, den Spezialfall aus der Schleife mit der Werteberechnung zu eliminieren.

    Das koennte man zum Beispiel so machen:

  • Hallo,

    ich würde das so machen:

    [code=php]def calc_temp(temperatures, weight_factor):
    weight_factors = []
    weight_factors.append(weight_factor)
    if len(temperatures) > 2:
    for _ in range(len(temperatures)-2):
    weight_factors.append(weight_factor*(1-weight_factor))
    weight_factors.append((1-weight_factor)**2)
    else:
    weight_factors.append(1-weight_factor)
    temperature = sum([temp*factor for temp, factor in zip(temperatures, weight_factors)])
    return temperature

    if __name__ == '__main__':
    print(calc_temp([15, 16], 0.7))
    print(calc_temp([10, 11, 12,], 0.8))
    print(calc_temp([20, 22, 24, 24], 0.7))[/php]

    Ob das für 4, 5, ... Werte auch stimmt kann ich nicht sagen, weil aus dem Ausgangspost nicht hervorgeht, die die Formel für 4, 5, ... Werte lautet.

    Gruß, noisefloor

  • Wenn ich das richtig sehe, haben bis jetzt alle vorgeschlagenen Lösungen einen Spezialfall ans Ende der Schleife gehängt - im letzten Fall halt durch ein der Schleife nachgestelltes append. Die einzige Lösung, das komplett zu umgehen, die mir eingefallen ist, sieht ungefähr so aus:

    Code
    for i in range(days):
      value += T[i]*(factor+rest*(i==days-1))*rest**i

    Ob das tatsächlich eleganter ist als der nachgestellte Spezialfall ist sicher Geschmackssache.

    P.S. marcuszurhorst: Kannst Du etwas über den physikalischen Hintergrund der Formel sagen?

    Einmal editiert, zuletzt von Manul (3. August 2017 um 10:59)

  • @ Noisefloor: Der sieht etwas länger und komplizierter aus als meiner...
    @ Manul: Sehr elegant... Was ist das? C oder Python? Was meinst du mit "Spezialfall"?

    Ich kriege beide Codes nicht zum Laufen. Habt ihr die getestet? Ergebnisse?

    Oh, man kann hier unliebsame Nutzer blockieren. Wie praktisch!

    Einmal editiert, zuletzt von Gnom (3. August 2017 um 11:26)

  • Hallo,

    Zitat

    Ich kriege beide Codes nicht zum Laufen. Habt ihr die getestet? Ergebnisse?

    Natürlich. Läuft mit Python 3.5 einwandfrei. Ergebnis für 2 und 3 Temperaturen entspricht dem, was auch "von Hand" raus kommt. Mal von den minimalen Fehlern abgesehen, die durch die Ungenauigkeiten beim Rechnen mit float-Werte entstehen.

    Gruß, noisefloor

  • Zitat von "Gnom" pid='293777' dateline='1501751651'


    @ Manul: Sehr elegant... Was ist das? C oder Python? Was meinst du mit "Spezialfall"?

    Ich kriege beide Codes nicht zum Laufen. Habt ihr die getestet? Ergebnisse?

    Python, ungetestet, hole ich gleich nach. Mit "Spezialfall" meine ich, daß nach dem Ende der Schleife jeweils noch eine Zusatzinstruktion stehen muß, um den letzten Term zu berechnen.
    Automatisch zusammengefügt:
    Nachtrag: Kompletter Code, getestet. Zum händischen Nachrechnen der Ergebnisse bin ich zu faul.

    Einmal editiert, zuletzt von Manul (3. August 2017 um 12:28)

  • Hallo zusammen!

    Danke für die Anrregungen.

    Bezüglich der Frage nach dem "physikalischen Hintergrund":
    Wie eingangs schon geschrieben geht es um eine Wettervorhersage.
    Da diese Vorhersage mit zunehmender Zeit immer ungenauer wird (meine Hypothese) möchte ich die Temperaturen unterschiedlich wichten.
    Sprich, die Vorhersage für den nächsten Tag fließt mit z.B. 0.7 ein, während die Vorhersage für die folgende Zeit mit den verbleibenden 0.3 eingeht.

    Sind jetzt mehr als zwei Tage zu berücksichtigen, dann Teile ich diese Zeit wieder im gleichen Verhältnis 7:3 auf.
    Und so weiter.


    Je mehr ich drüber nachdenke, desto mehr stelle ich meinen Ansatz aber inzwischen in Frage.
    Es wäre viel einfacher gewesen, wenn ich einfach 0.7 und dann für alle weiteren Werte (0.7 * 0.2** i) genutzt hätte.
    Dann wäre die Summe aller Wichtungsfaktoren zwar nicht 1.000000x gewesen, aber ich könnte damit den "Spezialfall" hinter der Schleifen eben vermeiden.

    Heute Abend werde ich mal Manuls Vorschlag ausprobieren.
    Alternativ fällt mir noch ein dass ich eine Mini-Funktion schreibe, welche nur die Faktoren ausrechnet und in eine Liste schreibt.
    Dann kann ich in der hier vorliegenden Funktion 1x die Liste ausrechnen lassen und dann sowohl die Liste als auch den JSON-Wert mit dem gleichen Index-Stand multiplizieren.

    Tja, was ist jetzt das Fazit? - Mit dem Kopf durch die Wand, obwohl es dafür im Prinzip keinen Grund gibt.
    Da hab ich mir selbst das Leben ziemlich kompiiziert gemacht :)

    Vielen Dank.

    Gruß,
    Marcus

  • Hallo,

    Zitat

    Alternativ fällt mir noch ein dass ich eine Mini-Funktion schreibe, welche nur die Faktoren ausrechnet und in eine Liste schreibt.
    Dann kann ich in der hier vorliegenden Funktion 1x die Liste ausrechnen lassen und dann sowohl die Liste als auch den JSON-Wert mit dem gleichen Index-Stand multiplizieren.


    Genau das macht mein Vorschlag ja :) In der Funktion `calc_temp` wird erst die Liste der Faktoren berechnet und in der Zeile vor dem `return` dann die theoretische Temperatur berechnet.


    Gruß, noisefloor

  • Zitat von "Manul" pid='293792' dateline='1501755782'


    Nachtrag: Kompletter Code, getestet. Zum händischen Nachrechnen der Ergebnisse bin ich zu faul.


    Hallo Manul,

    der Code scheint nicht korrekt zu sein:

    Code
    for i in range(days):
      print("Vorher:   Index: ", str(i), " - Faktor: ", factor, " - Rest: ", rest, " - Temperatur: ", T[i], " - Value: ", value)
     value += T[i]*(factor+rest*(i==days-1))*rest**i
     print("Nachher:  Index: ", str(i), " - Faktor: ", factor, " - Rest: ", rest, " - Temperatur: ", T[i], " - Value: ", value)
     print("--------------------------------------")
    
    
    print(value)


    Ergibt bei mir:

    Der Rest wird nicht reduziert und alles immer mit dem gleichen Faktor gewichtet.
    Muss ich mir heute Abend mal anschauen.

    Gruß,
    Marcus

  • Hallo Marcus,

    rest und factor bleiben konstant, das ist richtig. Jede einzelne Temperatur wird aber mit dem Faktor

    Code
    (factor+rest*(i==days-1))*rest**i

    multipliziert, der sich natürlich bei jedem Schleifendurchlauf ändert. Wenn man sich mal nur die Faktoren ausgeben lässt, kommen genau Deine angegebenen raus:

    Was den physikalischen Hintergrund angeht: Ich habe noch nicht ganz verstanden, welche Temperatur Du vorhersagen möchtest. Die Vorhersage für übermorgen ist sicher mit einer höheren Unsicherheit belastet als die für morgen - für übermorgen ist sie aber trotzdem die bessere Vorhersage. Für morgen ist sie hingegen überhaupt nicht relevant.

  • Hallo nochmal,

    ich möchte mir eine Gartenbewässerung basteln.
    Mein Grundstück wird partitioniert, und jedem Abschnitt wird eine "Grundbewässerungsdauer" zugewiesen. (abhängig davon ob da Blumen, Hecke, Rasen, Gemüse, ... etc wächst).

    Diese Grundzeit möchte ich dann noch ein wenig tunen abhängig von:

    • echter, gemessener Niederschlag der letzten 1-2 Tage
    • tatsächlicher Bewässerungsdauer meiner Steuerung vom Vortag
    • erwartete Niederschlagsmenge für die nächsten xyz Tage
    • erwartete Temperaturen für die nächsten xyz Tage


    Am Ende wir die "Grundbewässerungsdauer" mehrmals multipliziert mit vielen Zahlen größer oder kleiner 1, und dann komme eine tatsächliche Bewässerungsdauer für dieses eine Event raus.

    Braucht man das? - Nein.
    Meteorologisch fundiert? - Unwahrscheinlich.
    Ist das kleingärtnerischer Unsinn? - Keine Ahnung.
    Macht es dennoch Spaß? -- Jawohl !!

    Ich spiele nun seit ein paar Tagen mit Python rum und überlege mir die ganze Logik eben selbst.
    Allerdings merke ich auch an so einem Beispiel, dass ich natürlich den "roten Faden" nicht verlieren darf.
    Momentan verzettele ich mich in meiner Begeisterung schnell auf Nebensächlichkeiten.

    Danke & Gruß,
    Marcus

  • Hallo Marcus,

    das Stichwort lautet Evapotranspiration.

    Das mit der unterschiedlichen Bewässerungsdauer halte für Humbug - und hat mit dem Wasserbedarf nichts zu tun. Ein Teil der Pflanzen werden ersaufen, andere vertrocknen.

    Beste Grüße

    Andreas

    Ich bin wirklich nicht darauf aus, Microsoft zu zerstören. Das wird nur ein völlig unbeabsichtigter Nebeneffekt sein.
    Linus Torvalds - "Vater" von Linux

    Linux is like a wigwam, no windows, no gates, but with an apache inside dancing samba, very hungry eating a yacc, a gnu and a bison.

  • Andreas: Ich würde das nicht ganz so pessimistisch sehen. Wenn die Grunddauer dem jeweiligen Bewuchs angemessen und die Variation nicht zu groß ist, liegt man damit vermutlich auch nicht schlechter, als wenn man von Hand nach Gefühl bewässert. Zugegebenermaßen wahrscheinlich auch nicht besser, aber ein massenhaftes Pflanzensterben würde ich eher nicht vermuten.

    marcus: Ich wollte Dir auch keineswegs den Spaß verderben, sondern war lediglich neugierig. Kleiner Tip: So ein Forum ist eine prima Möglichkeit, seine Gedanken und Überlegungen aufzuschreiben und zu teilen. Das kann erstens beim Behalten des roten Fadens helfen und zweitens kriegt man möglicherweise ein paar nützliche Hinweise. Ich zumindest wäre interessiert zu sehen, welche Überlegungen hinter Deinen Formeln stecken.

  • Hallo Manul,

    ich wollte nochmal meine "Grundgedanken" erläutern. Jetzt ist es aber so ausführlich geworden, dass es hier nicht mehr hin gehört.
    Meine Gartenbewässerung

    Danke für die Hilfe von allen. Ich habe letztlich die Formel von Manul genommen:

    Code
    # Following equation has been provided by user Manul in the german Raspberry Pi forum
    # https://forum-raspberrypi.de/forum/thread/35434-benoetige-hilfe-bei-formeln-in-einer-schleife/?pid=293772#pid293772
    temperature_avg += temperature * (progression + remainder * (i==days-1)) * remainder**i

    Aber wie festgestellt ist meteorologisch da eh nichts hinter. :s


    Gruß,
    Marcus

    Einmal editiert, zuletzt von marcuszurhorst (6. August 2017 um 13:55)

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!