Fitten von Zeitkurven

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.
Benutzeravatar
sparrow
User
Beiträge: 4538
Registriert: Freitag 17. April 2009, 10:28

Überheblich war das keineswegs gemeint. Ich war nur neugierig, weil sich das Fass von "Herrschern", "mit Fehlern vollgestopften Kalendern" und der Raumkrümmung für mich schon sehr groß angefühlt hat.
zegru
User
Beiträge: 60
Registriert: Freitag 9. Oktober 2020, 09:22

Zurück zur ursprünglichen Frage: Ich habe nun folgenden Code geschrieben, in dem ich immerzu hin- und herkonvertiere:

Code: Alles auswählen

import datetime
from matplotlib import pyplot as plt, ticker
import scipy
import numpy as np

def quadratic(x: float, a: float, b: float, c: float):
    return a * x * x + b * x + c

def make_label(value, pos):
    return value.strftime("%m.%y")

measurements = [(datetime.date(2024, 12, 1), 10.0),
                (datetime.date(2024, 12, 2), 11.2),
                (datetime.date(2024, 12, 3), 14.3),
                (datetime.date(2024, 12, 4), 10.0),
                (datetime.date(2024, 12, 5), 3.0),
                (datetime.date(2024, 12, 6), 1.0),
                ]

measurements_x = [measurement[0] for measurement in measurements]
measurements_x_as_datetime = [datetime.datetime.combine(measurement[0], datetime.datetime.min.time())
                               for measurement in measurements]
measurements_x_as_timestamp = [measurement.timestamp()
                               for measurement in measurements_x_as_datetime]
measurements_y = [measurement[1] for measurement in measurements]

popt, pcov = scipy.optimize.curve_fit(quadratic, measurements_x_as_timestamp, measurements_y)
fitted_x_as_timestamp = np.linspace(measurements_x_as_timestamp[0],
                                    measurements_x_as_timestamp[-1],
                                    1000)  # Many points in the right range
fitted_x_as_datetime = [datetime.datetime.fromtimestamp(timestamp) for timestamp in fitted_x_as_timestamp.tolist()]
fitted_y = [quadratic(x, *popt) for x in fitted_x_as_timestamp]

plt.grid(True)
#plt.axes().xaxis.set_major_formatter(ticker.FuncFormatter(make_label))
plt.scatter(measurements_x_as_datetime, [m[1] for m in measurements], color="r")
plt.plot(fitted_x_as_datetime, fitted_y, color="b")
plt.show()
Was mich hier etwas misstrauisch macht;
  • Es ist ziemlich viel boilerplate
  • Wenn man den Kommentar vor ´set_major_formatter()´ entfernt, gibt es die Fehlermeldung `AttributeError: 'numpy.float64' object has no attribute 'strftime'`
  • Beim Aufruf von `curve_fit` gibt es die Warnung `too many values to unpack` in Pycharm
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Man kann sich da einiges sparen wenn man Numpy's `datetime64`-Typ verwendet. Einen Formatter gibt's dafür auch. (Macht natürlich nicht so viel Sinn Monat und Jahr zu formatieren wenn alle Datenpunkte aus dem gleichen Monat und Jahr sind. :-))

Code: Alles auswählen

from datetime import date as Date

import numpy as np
import scipy
from matplotlib import pyplot as plt
from matplotlib.dates import DateFormatter


def quadratic(x: float, a: float, b: float, c: float):
    return a * x * x + b * x + c


def main():
    measurements = [
        (Date(2024, 12, 1), 10.0),
        (Date(2024, 12, 2), 11.2),
        (Date(2024, 12, 3), 14.3),
        (Date(2024, 12, 4), 10.0),
        (Date(2024, 12, 5), 3.0),
        (Date(2024, 12, 6), 1.0),
    ]
    measurements_x = np.array(
        [measurement[0] for measurement in measurements], dtype="datetime64[s]"
    )
    measurements_y = [measurement[1] for measurement in measurements]

    popt, _pcov = scipy.optimize.curve_fit(
        quadratic, measurements_x, measurements_y
    )
    #
    # Many points in the right range.
    #
    fitted_x = np.linspace(
        measurements_x[0].astype("f8"),
        measurements_x[-1].astype("f8"),
        1000,
        dtype="datetime64[s]",
    )
    fitted_y = [quadratic(x, *popt) for x in fitted_x.astype("f8")]

    plt.axes().xaxis.set_major_formatter(DateFormatter("%m.%y"))
    plt.scatter(measurements_x, measurements_y, color="r")
    plt.plot(fitted_x, fitted_y, color="b")
    plt.grid(True)
    plt.show()


if __name__ == "__main__":
    main()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten