Seite 2 von 2

Re: Fitten von Zeitkurven

Verfasst: Sonntag 22. Dezember 2024, 22:26
von sparrow
Ü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.

Re: Fitten von Zeitkurven

Verfasst: Donnerstag 26. Dezember 2024, 17:26
von zegru
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

Re: Fitten von Zeitkurven

Verfasst: Freitag 1. August 2025, 15:18
von __blackjack__
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()