Как сделать подпись значений на графике и найти корреляцию между двумя графиками?
Коллеги, всем привет! Имею следующие данные:
import matplotlib.pyplot as plt
weather_data = {
'01.12': -4,
'02.12': -5,
'03.12': -5,
'04.12': -7,
'05.12': -10,
'06.12': -11,
'07.12': -11,
'08.12': -13,
'09.12': -13,
'10.12': -11,
'11.12': -6,
'12.12': -5,
'13.12': -7,
'14.12': -9,
'15.12': -8,
'16.12': -4,
'17.12': +2,
'18.12': +2,
'19.12': +4,
'20.12': +3,
'21.12': +1,
'22.12': +1,
'23.12': +1
}
value_clients = {
'01.12': 285,
'02.12': 496,
'03.12': 487,
'04.12': 254,
'05.12': 190,
'06.12': 236,
'07.12': 206,
'08.12': 267,
'09.12': 452,
'10.12': 384,
'11.12': 218,
'12.12': 252,
'13.12': 254,
'14.12': 265,
'15.12': 241,
'16.12': 425,
'17.12': 369,
'18.12': 256,
'19.12': 186,
'20.12': 255,
'21.12': 238,
'22.12': 277,
'23.12': 347
}
days = list(weather_data.keys())
temperatures = list(weather_data.values())
days = list(value_clients.keys())
value = list(value_clients.values())
# Создание графика
plt.figure(figsize=(15, 5)) # Указываем размер графика
plt.plot(days, temperatures, marker='o', linestyle='-', color='b') # График температуры
plt.title('Температура в Твери по дням') # Заголовок графика
plt.xlabel('День недели') # Ось X
plt.ylabel('Температура, °C') # Ось Y
plt.grid(True, which='both', linestyle='--', linewidth=0.5) # Сетка
plt.tight_layout() # Автоматическое распределение пространства
# Создание второго графика
plt.figure(figsize=(15, 5)) # Указываем размер графика
plt.plot(days, value, marker='o', linestyle='-', color='r') # График температуры
plt.title('Количество клиентов посетивших комплекс') # Заголовок графика
plt.xlabel('День месяца') # Ось X
plt.ylabel('Количество человек') # Ось Y
plt.grid(True, which='both', linestyle='-', linewidth=0.5) # Сетка
plt.tight_layout() # Автоматическое распределение пространства
# Отображение графика
plt.show()
Далее он отображает мне следующий графики:
Как мне добавить подписи значений на каждую точку графика? И ещё один вопрос, как мне найти корреляцию между двумя этими графиками?
Ответы (1 шт):
Сначала отвечу на второй вопрос. Чисто даже визуально видно, что этом графике корреляция явно слабая ("горбы" на втором графике явно выбиваются, да и общий тренд немного разный. Но. На втором графике явно есть "сезонность" в виде сильной зависимости от рабочих/выходных дней. Проверим эту гипотезу, добавим в данные признак "выходные", посмотрим корреляции признаков с клиентами и попробуем натренировать линейную регрессию:
import pandas as pd
from sklearn.linear_model import RidgeCV
from sklearn.metrics import mean_squared_error
import dateutil as du
df = pd.DataFrame({'day': days, 'temp': temperatures, 'clients': value})
df['day'] = pd.to_datetime(df.day + ".2023", dayfirst=True)
print(df.corr()['clients'])
df['weekend'] = (df.day.dt.dayofweek > 4).astype(int)
print(df.corr()['clients'])
X = df[['temp', 'weekend']]
y = df[['clients']]
lr = RidgeCV()
lr.fit(X, y)
print(lr.coef_)
y_pred = lr.predict(X)
df['predict'] = y_pred
print(f'RMSE: {mean_squared_error(y, y_pred)**0.5}')
df = df.set_index('day')
df[['clients', 'predict']].plot()
Вывод:
day -0.218086
temp -0.063177
clients 1.000000
Name: clients, dtype: float64
day -0.218086
temp -0.063177
clients 1.000000
weekend 0.909184
Name: clients, dtype: float64
[[ -1.08625212 176.72790901]]
RMSE: 37.60443795836316
Как видно, корреляция клиентов от температуры очень маленькая, это почти ничего не даст. Но если добавить фичу "выходной", то с ней корреляция будет 0.9, это отлично уже. Можно довольно точно предсказывать число клиентов, опираясь на то, выходной ли день и дополнительно на температуру.
О том, как ещё можно эти результаты трактовать. Посмотрите на коэффициенты линейной регрессии. У температуры коэффициент примерно -1, т.е. на каждый градус повышения температуры количество клиентов уменьшается на 1. А вот у признака "выходной" коэффициент почти 177, т.е. выходной день сразу даёт +177 клиентов.
Среднеквадратичная ошибка RMSE нашей модели получилась примерно 38, т.е. грубо говоря данная модель ошибается "в среднем по больнице" где-то на 40 человек в день, что, наверное, довольно неплохо для такой простой модели. Но, если вернуться к корреляции с температурой, то при среднеквадратичной ошибке 40 изменение на 1 клиента в зависимости от температуры - это вообще ни о чём и может быть просто погрешностью измерения или модели. Это нужно иметь в виду.
P.S. Подписи можно добавить к соответствующим графикам примерно так:
for d,t in zip(days, temperatures):
plt.text(d, t+0.2, t);
...
for d,t in zip(days, value):
plt.text(d, t+0.2, t);
P.P.S. Если построить ту же линейную модель только по одному признаку, то получится:
- На одной температуре
RMSE=91, это гораздо хуже. - На одном признаке "выходной"
RMSE=38, то есть практически без изменения, что с температурой, что без неё, что и было в общем понятно.
Вот график предсказания на одной только температуре. Это практически просто среднее значение числа посетителей.
Более того, если взять константное предсказание на все дни - среднее значение посетителей в день за этот период (около 297 в день), то получим ту же самую метрику RMSE=91, что и с моделью на признаке "температура". Лишний раз убеждаемся, что температура практически ничего не даёт для предсказания посетителей.





