Fitten von Zeitkurven
Zurück zur ursprünglichen Frage: Ich habe nun folgenden Code geschrieben, in dem ich immerzu hin- und herkonvertiere:
Was mich hier etwas misstrauisch macht;
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()
- 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
- __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